[benchmarks] Remove Dart 2 benchmarks

Change-Id: I69d03bb874b015494c7af80ceffcc4482b3ec688
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/421887
Reviewed-by: Stephen Adams <sra@google.com>
Commit-Queue: Mayank Patke <fishythefish@google.com>
This commit is contained in:
Mayank Patke
2025-04-16 17:15:01 -07:00
committed by Commit Queue
parent e480c74d01
commit 2385d2fb11
81 changed files with 0 additions and 13008 deletions
@@ -1,317 +0,0 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Micro-benchmark for testing async/await performance in presence of
// different number of live values across await.
// @dart=2.9
import 'dart:async';
import 'package:benchmark_harness/benchmark_harness.dart';
class MockClass {
static final String str = "${int.parse('42')}";
static final List<int> list = List<int>.filled(
int.parse('3'),
int.parse('42'),
);
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
String get1() => str;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
List<int> get2() => list;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
void use1(String a0) => a0.length;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
void use2(String a0, List<int> a1) => a0.length + a1.length;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
void use4(String a0, List<int> a1, String a2, List<int> a3) =>
a0.length + a1.length + a2.length + a3.length;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
void use8(
String a0,
List<int> a1,
String a2,
List<int> a3,
String a4,
List<int> a5,
String a6,
List<int> a7,
) =>
a0.length +
a1.length +
a2.length +
a3.length +
a4.length +
a5.length +
a6.length +
a7.length;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<void> asyncMethod() async {}
}
class MockClass2 {
static int val1 = int.parse('42');
static int val2 = int.parse('43');
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
int get1() => val1;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
int get2() => val2;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
void use1(int a0) => a0;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
void use2(int a0, int a1) => a0 + a1;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
void use4(int a0, int a1, int a2, int a3) => a0 + a1 + a2 + a3;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<void> asyncMethod() async {}
}
class LiveVarsBench extends AsyncBenchmarkBase {
LiveVarsBench(String name) : super(name);
@override
Future<void> exercise() async {
// These micro-benchmarks are too small, so
// make a larger number of iterations per measurement.
for (var i = 0; i < 10000; i++) {
await run();
}
}
}
class LiveObj1 extends LiveVarsBench {
LiveObj1() : super('AsyncLiveVars.LiveObj1');
final field1 = MockClass();
@override
Future<void> run() async {
final obj1 = field1.get1();
await field1.asyncMethod();
field1.use1(obj1);
await field1.asyncMethod();
field1.use1(obj1);
await field1.asyncMethod();
field1.use1(obj1);
}
}
class LiveObj2 extends LiveVarsBench {
LiveObj2() : super('AsyncLiveVars.LiveObj2');
final field1 = MockClass();
@override
Future<void> run() async {
final obj1 = field1.get1();
final obj2 = field1.get2();
await field1.asyncMethod();
field1.use1(obj1);
await field1.asyncMethod();
field1.use1(obj1);
await field1.asyncMethod();
field1.use2(obj1, obj2);
}
}
class LiveObj4 extends LiveVarsBench {
LiveObj4() : super('AsyncLiveVars.LiveObj4');
final field1 = MockClass();
final field2 = MockClass();
@override
Future<void> run() async {
final obj1 = field1.get1();
final obj2 = field1.get2();
final obj3 = field2.get1();
final obj4 = field2.get2();
await field1.asyncMethod();
field1.use1(obj1);
await field1.asyncMethod();
field2.use1(obj3);
await field2.asyncMethod();
field1.use4(obj1, obj2, obj3, obj4);
}
}
class LiveObj8 extends LiveVarsBench {
LiveObj8() : super('AsyncLiveVars.LiveObj8');
final field1 = MockClass();
final field2 = MockClass();
final field3 = MockClass();
final field4 = MockClass();
@override
Future<void> run() async {
final obj1 = field1.get1();
final obj2 = field1.get2();
final obj3 = field2.get1();
final obj4 = field2.get2();
final obj5 = field3.get1();
final obj6 = field3.get2();
final obj7 = field4.get1();
final obj8 = field4.get2();
await field1.asyncMethod();
field1.use1(obj1);
await field2.asyncMethod();
field3.use2(obj5, obj6);
await field4.asyncMethod();
field2.use8(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8);
}
}
class LiveObj16 extends LiveVarsBench {
LiveObj16() : super('AsyncLiveVars.LiveObj16');
final field1 = MockClass();
final field2 = MockClass();
final field3 = MockClass();
final field4 = MockClass();
final field5 = MockClass();
final field6 = MockClass();
final field7 = MockClass();
final field8 = MockClass();
@override
Future<void> run() async {
final obj1 = field1.get1();
final obj2 = field1.get2();
final obj3 = field2.get1();
final obj4 = field2.get2();
final obj5 = field3.get1();
final obj6 = field3.get2();
final obj7 = field4.get1();
final obj8 = field4.get2();
final obj9 = field5.get1();
final obj10 = field5.get2();
final obj11 = field6.get1();
final obj12 = field6.get2();
final obj13 = field7.get1();
final obj14 = field7.get2();
final obj15 = field8.get1();
final obj16 = field8.get2();
await field1.asyncMethod();
field1.use1(obj1);
await field2.asyncMethod();
field5.use2(obj11, obj12);
await field4.asyncMethod();
field2.use8(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8);
field3.use8(obj9, obj10, obj11, obj12, obj13, obj14, obj15, obj16);
}
}
class LiveInt1 extends LiveVarsBench {
LiveInt1() : super('AsyncLiveVars.LiveInt1');
final field1 = MockClass2();
@override
Future<void> run() async {
final int1 = field1.get1();
await field1.asyncMethod();
field1.use1(int1);
await field1.asyncMethod();
field1.use1(int1);
await field1.asyncMethod();
field1.use1(int1);
}
}
class LiveInt4 extends LiveVarsBench {
LiveInt4() : super('AsyncLiveVars.LiveInt4');
final field1 = MockClass2();
final field2 = MockClass2();
@override
Future<void> run() async {
final int1 = field1.get1();
final int2 = field1.get2();
final int3 = field2.get1();
final int4 = field2.get2();
await field1.asyncMethod();
field1.use1(int1);
await field1.asyncMethod();
field2.use1(int3);
await field2.asyncMethod();
field1.use4(int1, int2, int3, int4);
}
}
class LiveObj2Int2 extends LiveVarsBench {
LiveObj2Int2() : super('AsyncLiveVars.LiveObj2Int2');
final field1 = MockClass();
final field2 = MockClass2();
@override
Future<void> run() async {
final obj1 = field1.get1();
final obj2 = field1.get2();
final int1 = field2.get1();
final int2 = field2.get2();
await field1.asyncMethod();
field1.use1(obj1);
await field1.asyncMethod();
field2.use1(int1);
await field2.asyncMethod();
field1.use2(obj1, obj2);
field2.use2(int1, int2);
}
}
class LiveObj4Int4 extends LiveVarsBench {
LiveObj4Int4() : super('AsyncLiveVars.LiveObj4Int4');
final field1 = MockClass();
final field2 = MockClass();
final field3 = MockClass2();
final field4 = MockClass2();
@override
Future<void> run() async {
final obj1 = field1.get1();
final obj2 = field1.get2();
final obj3 = field2.get1();
final obj4 = field2.get2();
final int1 = field3.get1();
final int2 = field3.get2();
final int3 = field4.get1();
final int4 = field4.get2();
await field1.asyncMethod();
field1.use1(obj1);
await field2.asyncMethod();
field3.use2(int2, int4);
await field4.asyncMethod();
field2.use4(obj1, obj2, obj3, obj4);
field4.use4(int1, int2, int3, int4);
}
}
Future<void> main() async {
final benchmarks = [
LiveObj1(),
LiveObj2(),
LiveObj4(),
LiveObj8(),
LiveObj16(),
LiveInt1(),
LiveInt4(),
LiveObj2Int2(),
LiveObj4Int4(),
];
for (final bench in benchmarks) {
await bench.report();
}
}
@@ -1,329 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// ignore_for_file: avoid_function_literals_in_foreach_calls
// @dart=2.9
import 'dart:math' show Random;
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:fixnum/fixnum.dart';
import 'native_version_dummy.dart'
if (dart.library.js) 'native_version_javascript.dart';
// Benchmark BigInt and Int64 formatting and parsing.
// A global sink that is used in the [check] method ensures that the results are
// not optimized.
dynamic sink1, sink2;
void check(bool sink2isEven) {
if (sink1.codeUnits.last.isEven != sink2isEven) {
throw StateError('Inconsistent $sink1 vs $sink2');
}
}
// These benchmarks measure digit-throughput for parsing and formatting.
//
// Each benchmark targets processing [requiredDigits] decimal digits, spread
// over a list of input values. This makes the benchmarks for different integer
// lengths roughly comparable. The number is chosen so that most benchmarks
// have very close to this number of digits. It corresponds to nine 4096-bit
// integers.
const requiredDigits = 11106;
class Benchmark extends BenchmarkBase {
final List<String> strings;
Benchmark(String name, int bits, {bool forInt = false})
: strings = generateStrings(bits, forInt),
super(name);
static List<String> generateStrings(int bits, bool forInt) {
final List<String> strings = [];
final BigInt seed = (BigInt.one << bits) - BigInt.one;
var b = seed;
var restartDelta = BigInt.zero;
var totalLength = 0;
while (totalLength < requiredDigits) {
if (b.bitLength < bits) {
restartDelta += seed >> 20;
restartDelta += BigInt.one;
// Restart from a slightly reduced seed to generate different numbers.
b = seed - restartDelta;
}
var string = b.toString();
// Web integers lose precision due to rounding for larger values. Make
// sure the string will round-trip correctly.
if (forInt) string = int.parse(string).toString();
strings.add(string);
totalLength += string.length;
var delta = b >> 8;
if (delta == BigInt.zero) delta = BigInt.one;
b = b - delta;
}
return strings;
}
}
class ParseBigIntBenchmark extends Benchmark {
ParseBigIntBenchmark(String name, int bits) : super(name, bits);
@override
void run() {
for (final s in strings) {
final b = BigInt.parse(s);
sink1 = s;
sink2 = b;
}
check(sink2.isEven);
}
}
class ParseInt64Benchmark extends Benchmark {
ParseInt64Benchmark(String name, int bits) : super(name, bits);
@override
void run() {
for (final s in strings) {
final b = Int64.parseInt(s);
sink1 = s;
sink2 = b;
}
check(sink2.isEven);
}
}
class ParseIntBenchmark extends Benchmark {
ParseIntBenchmark(String name, int bits) : super(name, bits, forInt: true);
@override
void run() {
for (final s in strings) {
final b = int.parse(s);
sink1 = s;
sink2 = b;
}
check(sink2.isEven);
}
}
class ParseJsBigIntBenchmark extends Benchmark {
ParseJsBigIntBenchmark(String name, int bits) : super(name, bits);
@override
void run() {
for (final s in strings) {
final b = nativeBigInt.parse(s);
sink1 = s;
sink2 = b;
}
check(nativeBigInt.isEven(sink2));
}
}
class FormatBigIntBenchmark extends Benchmark {
final List<BigInt> values = [];
FormatBigIntBenchmark(String name, int bits) : super(name, bits);
@override
void setup() {
for (String s in strings) {
final BigInt b = BigInt.parse(s);
values.add(b - BigInt.one); // We add 'one' back later.
}
}
@override
void run() {
final one = BigInt.one;
for (final b0 in values) {
// Instances might cache `toString()`, so use arithmetic to create a new
// instance to try to protect against measuring a cached string.
final b = b0 + one;
final s = b.toString();
sink1 = s;
sink2 = b;
}
check(sink2.isEven);
}
}
class FormatIntBenchmark extends Benchmark {
final List<int> values = [];
FormatIntBenchmark(String name, int bits) : super(name, bits, forInt: true);
@override
void setup() {
for (String s in strings) {
final int b = int.parse(s);
values.add(b - 4096); // We add this back later.
}
}
@override
void run() {
for (final b0 in values) {
// Instances might cache `toString()`, so use arithmetic to create a new
// instance to try to protect against measuring a cached string. We use
// 4096 to avoid the arithmetic being a no-op due to rounding on web
// integers (i.e. doubles).
final b = b0 + 4096;
final s = b.toString();
sink1 = s;
sink2 = b;
}
check(sink2.isEven);
}
}
class FormatInt64Benchmark extends Benchmark {
final List<Int64> values = [];
FormatInt64Benchmark(String name, int bits) : super(name, bits);
@override
void setup() {
for (String s in strings) {
final b = Int64.parseInt(s);
values.add(b - Int64.ONE); // We add this back later.
}
}
@override
void run() {
final one = Int64.ONE;
for (final b0 in values) {
// Instances might cache `toString()`, so use arithmetic to create a new
// instance to try to protect against measuring a cached string.
final b = b0 + one;
final s = b.toStringUnsigned();
sink1 = s;
sink2 = b;
}
check(sink2.isEven);
}
}
class FormatJsBigIntBenchmark extends Benchmark {
final List<Object> values = [];
FormatJsBigIntBenchmark(String name, int bits) : super(name, bits);
@override
void setup() {
final one = nativeBigInt.one;
for (String s in strings) {
final b = nativeBigInt.parse(s);
values.add(nativeBigInt.subtract(b, one)); // We add this back later.
}
}
@override
void run() {
final one = nativeBigInt.one;
for (final b0 in values) {
// Instances might cache `toString()`, so use arithmetic to create a new
// instance to try to protect against measuring a cached string.
final b = nativeBigInt.add(b0, one);
final s = nativeBigInt.toStringMethod(b);
sink1 = s;
sink2 = b;
}
check(nativeBigInt.isEven(sink2));
}
}
/// [DummyBenchmark] instantly returns a fixed 'slow' result.
class DummyBenchmark extends BenchmarkBase {
DummyBenchmark(String name) : super(name);
@override
// A rate of one run per 2s, with a millisecond of noise. Some variation is
// needed for Golem's noise-based filtering and regression detection.
double measure() => (2000 + Random().nextDouble() - 0.5) * 1000;
}
/// Create [ParseJsBigIntBenchmark], or a dummy benchmark if JavaScript BigInt
/// is not available. This is to satisfy Golem's constraint that group
/// benchmarks always produce results for the same set of series.
BenchmarkBase Function() selectParseNativeBigIntBenchmark(
String name,
int bits,
) {
return nativeBigInt.enabled
? () => ParseJsBigIntBenchmark(name, bits)
: () => DummyBenchmark(name);
}
/// Create [FormatJsBigIntBenchmark], or a dummy benchmark if JavaScript BigInt
/// is not available. This is to satisfy Golem's constraint that group
/// benchmarks always produce results for the same set of series.
BenchmarkBase Function() selectFormatNativeBigIntBenchmark(
String name,
int bits,
) {
return nativeBigInt.enabled
? () => FormatJsBigIntBenchmark(name, bits)
: () => DummyBenchmark(name);
}
void main() {
final benchmarks = [
() => ParseIntBenchmark('Int.parse.0009.bits', 9),
() => ParseIntBenchmark('Int.parse.0032.bits', 32),
// Use '63' bits to avoid 64-bit arithmetic overflowing to negative. Keep
// the name as '64' to help comparisons. The effect of an incorrect number
// is reduced since benchmark results are normalized to a 'per digit' score
() => ParseIntBenchmark('Int.parse.0064.bits', 63),
() => ParseInt64Benchmark('Int64.parse.0009.bits', 9),
() => ParseInt64Benchmark('Int64.parse.0032.bits', 32),
() => ParseInt64Benchmark('Int64.parse.0064.bits', 64),
() => ParseBigIntBenchmark('BigInt.parse.0009.bits', 9),
() => ParseBigIntBenchmark('BigInt.parse.0032.bits', 32),
() => ParseBigIntBenchmark('BigInt.parse.0064.bits', 64),
() => ParseBigIntBenchmark('BigInt.parse.0256.bits', 256),
() => ParseBigIntBenchmark('BigInt.parse.1024.bits', 1024),
() => ParseBigIntBenchmark('BigInt.parse.4096.bits', 4096),
selectParseNativeBigIntBenchmark('JsBigInt.parse.0009.bits', 9),
selectParseNativeBigIntBenchmark('JsBigInt.parse.0032.bits', 32),
selectParseNativeBigIntBenchmark('JsBigInt.parse.0064.bits', 64),
selectParseNativeBigIntBenchmark('JsBigInt.parse.0256.bits', 256),
selectParseNativeBigIntBenchmark('JsBigInt.parse.1024.bits', 1024),
selectParseNativeBigIntBenchmark('JsBigInt.parse.4096.bits', 4096),
() => FormatIntBenchmark('Int.toString.0009.bits', 9),
() => FormatIntBenchmark('Int.toString.0032.bits', 32),
() => FormatIntBenchmark('Int.toString.0064.bits', 63), // '63': See above.
() => FormatInt64Benchmark('Int64.toString.0009.bits', 9),
() => FormatInt64Benchmark('Int64.toString.0032.bits', 32),
() => FormatInt64Benchmark('Int64.toString.0064.bits', 64),
() => FormatBigIntBenchmark('BigInt.toString.0009.bits', 9),
() => FormatBigIntBenchmark('BigInt.toString.0032.bits', 32),
() => FormatBigIntBenchmark('BigInt.toString.0064.bits', 64),
() => FormatBigIntBenchmark('BigInt.toString.0256.bits', 256),
() => FormatBigIntBenchmark('BigInt.toString.1024.bits', 1024),
() => FormatBigIntBenchmark('BigInt.toString.4096.bits', 4096),
selectFormatNativeBigIntBenchmark('JsBigInt.toString.0009.bits', 9),
selectFormatNativeBigIntBenchmark('JsBigInt.toString.0032.bits', 32),
selectFormatNativeBigIntBenchmark('JsBigInt.toString.0064.bits', 64),
selectFormatNativeBigIntBenchmark('JsBigInt.toString.0256.bits', 256),
selectFormatNativeBigIntBenchmark('JsBigInt.toString.1024.bits', 1024),
selectFormatNativeBigIntBenchmark('JsBigInt.toString.4096.bits', 4096),
];
// Warm up all benchmarks to ensure consistent behaviors of shared code.
benchmarks.forEach(
(bm) =>
bm()
..setup()
..run()
..run(),
);
benchmarks.forEach((bm) => bm().report());
}
@@ -1,25 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
abstract class NativeBigIntMethods {
bool get enabled;
Object parse(String string);
String toStringMethod(Object value);
Object fromInt(int i);
Object get one;
Object get eight;
int bitLength(Object value);
bool isEven(Object value);
Object add(Object left, Object right);
Object shiftLeft(Object value, Object count);
Object shiftRight(Object value, Object count);
Object subtract(Object left, Object right);
}
@@ -1,51 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'native_version.dart';
const NativeBigIntMethods nativeBigInt = _DummyMethods();
class _DummyMethods implements NativeBigIntMethods {
const _DummyMethods();
@override
bool get enabled => false;
static Object bad(String message) => UnimplementedError(message);
@override
Object parse(String string) => throw bad('parse');
@override
String toStringMethod(Object value) => throw bad('toStringMethod');
@override
Object fromInt(int i) => throw bad('fromInt');
@override
Object get one => throw bad('one');
@override
Object get eight => throw bad('eight');
@override
int bitLength(Object value) => throw bad('bitLength');
@override
bool isEven(Object value) => throw bad('isEven');
@override
Object add(Object left, Object right) => throw bad('add');
@override
Object shiftLeft(Object value, Object count) => throw bad('shiftLeft');
@override
Object shiftRight(Object value, Object count) => throw bad('shiftRight');
@override
Object subtract(Object left, Object right) => throw bad('subtract');
}
@@ -1,130 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
@JS()
library native_version_javascript;
import 'package:js/js.dart';
import 'native_version.dart';
const NativeBigIntMethods nativeBigInt = _Methods();
@JS('eval')
external Object _eval(String s);
@JS('bigint_parse')
external Object _parse(String s);
@JS('bigint_toString')
external String _toStringMethod(Object o);
@JS('bigint_bitLength')
external int _bitLength(Object o);
@JS('bigint_isEven')
external bool _isEven(Object o);
@JS('bigint_add')
external Object _add(Object left, Object right);
@JS('bigint_shiftLeft')
external Object _shiftLeft(Object o, Object i);
@JS('bigint_shiftRight')
external Object _shiftRight(Object o, Object i);
@JS('bigint_subtract')
external Object _subtract(Object left, Object right);
@JS('bigint_fromInt')
external Object _fromInt(int i);
class _Methods implements NativeBigIntMethods {
static bool _initialized = false;
static bool _enabled = false;
const _Methods();
@override
bool get enabled {
if (!_initialized) {
_initialize();
}
return _enabled;
}
void _initialize() {
_initialized = true;
try {
_setup();
_enabled = true;
} catch (e) {
// We get here if the JavaScript implementation does not have BigInt (or
// run in a stand-alone JavaScript implementation without the right
// 'preamble').
//
// Print so we can see what failed.
print(e);
}
}
@override
Object parse(String string) => _parse(string);
@override
String toStringMethod(Object value) => _toStringMethod(value);
@override
Object fromInt(int i) => _fromInt(i);
@override
Object get one => _one;
@override
Object get eight => _eight;
@override
int bitLength(Object value) => _bitLength(value);
@override
bool isEven(Object value) => _isEven(value);
@override
Object add(Object left, Object right) => _add(left, right);
@override
Object shiftLeft(Object value, Object count) => _shiftLeft(value, count);
@override
Object shiftRight(Object value, Object count) => _shiftRight(value, count);
@override
Object subtract(Object left, Object right) => _subtract(left, right);
}
void _setup() {
_one = _eval('1n'); // Throws if JavaScript does not have BigInt.
_eight = _eval('8n');
_eval('self.bigint_parse = function parse(s) { return BigInt(s); }');
_eval('self.bigint_toString = function toString(b) { return b.toString(); }');
_eval('self.bigint_add = function add(a, b) { return a + b; }');
_eval('self.bigint_shiftLeft = function shl(v, i) { return v << i; }');
_eval('self.bigint_shiftRight = function shr(v, i) { return v >> i; }');
_eval('self.bigint_subtract = function subtract(a, b) { return a - b; }');
_eval('self.bigint_fromInt = function fromInt(i) { return BigInt(i); }');
_eval(
'self.bigint_bitLength = function bitLength(b) {'
'return b == 0 ? 0 : (b < 0 ? ~b : b).toString(2).length;'
'}',
);
_eval('self.bigint_isEven = function isEven(b) { return (b & 1n) == 0n; }');
}
// `dynamic` to allow null initialization pre- and post- NNBD.
dynamic _one;
dynamic _eight;
-898
View File
@@ -1,898 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Micro-benchmarks for sync/sync*/async/async* functionality.
// @dart=2.9
import 'dart:async';
const int iterationLimitAsync = 200;
const int sumOfIterationLimitAsync =
iterationLimitAsync * (iterationLimitAsync - 1) ~/ 2;
const int iterationLimitSync = 5000;
const int sumOfIterationLimitSync =
iterationLimitSync * (iterationLimitSync - 1) ~/ 2;
Future main() async {
final target = Target();
final target2 = Target2();
final target3 = Target3();
// Ensure the call sites will have another target in the ICData.
await performAwaitCallsClosureTargetPolymorphic(returnAsync);
await performAwaitCallsClosureTargetPolymorphic(returnFuture);
await performAwaitCallsClosureTargetPolymorphic(returnFutureOr);
await performAwaitAsyncCallsInstanceTargetPolymorphic(target);
await performAwaitAsyncCallsInstanceTargetPolymorphic(target2);
await performAwaitAsyncCallsInstanceTargetPolymorphic(target3);
await performAwaitFutureCallsInstanceTargetPolymorphic(target);
await performAwaitFutureCallsInstanceTargetPolymorphic(target2);
await performAwaitFutureCallsInstanceTargetPolymorphic(target3);
await performAwaitFutureOrCallsInstanceTargetPolymorphic(target);
await performAwaitFutureOrCallsInstanceTargetPolymorphic(target2);
await performAwaitFutureOrCallsInstanceTargetPolymorphic(target3);
performSyncCallsInstanceTargetPolymorphic(target);
performSyncCallsInstanceTargetPolymorphic(target2);
performSyncCallsInstanceTargetPolymorphic(target3);
await performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target);
await performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target2);
await performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target3);
await performAwaitForIterationPolymorphic(generateNumbersAsyncStar);
await performAwaitForIterationPolymorphic(generateNumbersAsyncStar2);
await performAwaitForIterationPolymorphic(generateNumbersManualAsync);
await performAwaitForIterationPolymorphic(generateNumbersAsyncStarManyYields);
performSyncIterationPolymorphic(generateNumbersSyncStar);
performSyncIterationPolymorphic(generateNumbersSyncStar2);
performSyncIterationPolymorphic(generateNumbersManual);
performSyncIterationPolymorphic(generateNumbersSyncStarManyYields);
await AsyncCallBenchmark(
'Calls.AwaitAsyncCall',
performAwaitAsyncCalls,
).report();
await AsyncCallBenchmark(
'Calls.AwaitAsyncCallClosureTargetPolymorphic',
() => performAwaitCallsClosureTargetPolymorphic(returnAsync),
).report();
await AsyncCallBenchmark(
'Calls.AwaitAsyncCallInstanceTargetPolymorphic',
() => performAwaitAsyncCallsInstanceTargetPolymorphic(target),
).report();
await AsyncCallBenchmark(
'Calls.AwaitFutureCall',
performAwaitFutureCalls,
).report();
await AsyncCallBenchmark(
'Calls.AwaitFutureCallClosureTargetPolymorphic',
() => performAwaitCallsClosureTargetPolymorphic(returnFuture),
).report();
await AsyncCallBenchmark(
'Calls.AwaitFutureCallInstanceTargetPolymorphic',
() => performAwaitFutureCallsInstanceTargetPolymorphic(target),
).report();
await AsyncCallBenchmark(
'Calls.AwaitFutureOrCall',
performAwaitFutureOrCalls,
).report();
await AsyncCallBenchmark(
'Calls.AwaitFutureOrCallClosureTargetPolymorphic',
() => performAwaitCallsClosureTargetPolymorphic(returnFutureOr),
).report();
await AsyncCallBenchmark(
'Calls.AwaitFutureOrCallInstanceTargetPolymorphic',
() => performAwaitFutureOrCallsInstanceTargetPolymorphic(target),
).report();
await AsyncCallBenchmark(
'Calls.AwaitFutureOrCallInstanceTargetPolymorphicManyAwaits',
() => performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target),
).report();
await AsyncCallBenchmark(
'Calls.AwaitForAsyncStarStreamPolymorphic',
() => performAwaitForIterationPolymorphic(generateNumbersAsyncStar),
).report();
await AsyncCallBenchmark(
'Calls.AwaitForAsyncStarStreamPolymorphicManyYields',
() =>
performAwaitForIterationPolymorphic(generateNumbersAsyncStarManyYields),
).report();
await AsyncCallBenchmark(
'Calls.AwaitForManualStreamPolymorphic',
() => performAwaitForIterationPolymorphic(generateNumbersManualAsync),
).report();
SyncCallBenchmark('Calls.SyncCall', performSyncCalls).report();
SyncCallBenchmark(
'Calls.SyncCallClosureTarget',
() => performSyncCallsClosureTarget(returnSync),
).report();
SyncCallBenchmark(
'Calls.SyncCallInstanceTargetPolymorphic',
() => performSyncCallsInstanceTargetPolymorphic(target),
).report();
SyncCallBenchmark(
'Calls.IterableSyncStarIterablePolymorphic',
() => performSyncIterationPolymorphic(generateNumbersSyncStar),
).report();
SyncCallBenchmark(
'Calls.IterableManualIterablePolymorphic',
() => performSyncIterationPolymorphic(generateNumbersManual),
).report();
SyncCallBenchmark(
'Calls.IterableManualIterablePolymorphicManyYields',
() => performSyncIterationPolymorphic(generateNumbersSyncStarManyYields),
).report();
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> performAwaitCallsClosureTargetPolymorphic(
FutureOr<int> Function(int) fun,
) async {
int sum = 0;
for (int i = 0; i < iterationLimitAsync; ++i) {
sum += await fun(i);
}
if (sum != sumOfIterationLimitAsync) throw 'BUG';
return iterationLimitAsync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> performAwaitAsyncCallsInstanceTargetPolymorphic(
Target target,
) async {
int sum = 0;
for (int i = 0; i < iterationLimitAsync; ++i) {
sum += await target.returnAsync(i);
}
if (sum != sumOfIterationLimitAsync) throw 'BUG';
return iterationLimitAsync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> performAwaitFutureCallsInstanceTargetPolymorphic(
Target target,
) async {
int sum = 0;
for (int i = 0; i < iterationLimitAsync; ++i) {
sum += await target.returnFuture(i);
}
if (sum != sumOfIterationLimitAsync) throw 'BUG';
return iterationLimitAsync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> performAwaitFutureOrCallsInstanceTargetPolymorphic(
Target target,
) async {
int sum = 0;
for (int i = 0; i < iterationLimitAsync; ++i) {
sum += await target.returnFutureOr(i);
}
if (sum != sumOfIterationLimitAsync) throw 'BUG';
return iterationLimitAsync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> performAwaitAsyncCalls() async {
int sum = 0;
for (int i = 0; i < iterationLimitAsync; ++i) {
sum += await returnAsync(i);
}
if (sum != sumOfIterationLimitAsync) throw 'BUG';
return iterationLimitAsync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> performAwaitFutureCalls() async {
int sum = 0;
for (int i = 0; i < iterationLimitAsync; ++i) {
sum += await returnFuture(i);
}
if (sum != sumOfIterationLimitAsync) throw 'BUG';
return iterationLimitAsync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> performAwaitFutureOrCalls() async {
int sum = 0;
for (int i = 0; i < iterationLimitAsync; ++i) {
sum += await returnFutureOr(i);
}
if (sum != sumOfIterationLimitAsync) throw 'BUG';
return iterationLimitAsync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(
Target t,
) async {
int sum = 0;
int i = 0;
final int blockLimit = iterationLimitAsync - (iterationLimitAsync % 80);
while (i < blockLimit) {
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
sum += await t.returnAsync(i++);
}
while (i < iterationLimitAsync) {
sum += await t.returnAsync(i++);
}
if (sum != sumOfIterationLimitAsync) throw 'BUG';
return iterationLimitAsync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> performAwaitForIterationPolymorphic(
Stream<int> Function(int) fun,
) async {
int sum = 0;
await for (int value in fun(iterationLimitAsync)) {
sum += value;
}
if (sum != sumOfIterationLimitAsync) throw 'BUG';
return iterationLimitAsync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
int performSyncCallsClosureTarget(int Function(int) fun) {
int sum = 0;
for (int i = 0; i < iterationLimitSync; ++i) {
sum += fun(i);
}
if (sum != sumOfIterationLimitSync) throw 'BUG';
return iterationLimitSync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
int performSyncCallsInstanceTargetPolymorphic(Target target) {
int sum = 0;
for (int i = 0; i < iterationLimitSync; ++i) {
sum += target.returnSync(i);
}
if (sum != sumOfIterationLimitSync) throw 'BUG';
return iterationLimitSync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
int performSyncCalls() {
int sum = 0;
for (int i = 0; i < iterationLimitSync; ++i) {
sum += returnSync(i);
}
if (sum != sumOfIterationLimitSync) throw 'BUG';
return iterationLimitSync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
int performSyncIterationPolymorphic(Iterable<int> Function(int) fun) {
int sum = 0;
for (int value in fun(iterationLimitSync)) {
sum += value;
}
if (sum != sumOfIterationLimitSync) throw 'BUG';
return iterationLimitSync;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
FutureOr<int> returnFutureOr(int i) => i;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> returnFuture(int i) => Future.value(i);
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> returnAsync(int i) async => i;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Stream<int> generateNumbersAsyncStar(int limit) async* {
for (int i = 0; i < limit; ++i) {
yield i;
}
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Stream<int> generateNumbersAsyncStar2(int limit) async* {
for (int i = 0; i < limit; ++i) {
yield i;
}
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Stream<int> generateNumbersManualAsync(int limit) {
int current = 0;
final controller = StreamController<int>(sync: true);
void emit() {
while (true) {
if (controller.isPaused || !controller.hasListener) return;
if (current < limit) {
controller.add(current++);
} else {
controller.close();
return;
}
}
}
void run() {
scheduleMicrotask(emit);
}
controller.onListen = run;
controller.onResume = run;
return controller.stream;
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
int returnSync(int i) => i;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Iterable<int> generateNumbersSyncStar(int limit) sync* {
for (int i = 0; i < limit; ++i) {
yield i;
}
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Iterable<int> generateNumbersSyncStar2(int limit) sync* {
for (int i = 0; i < limit; ++i) {
yield i;
}
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Iterable<int> generateNumbersManual(int limit) =>
Iterable<int>.generate(limit, (int i) => i);
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Iterable<int> generateNumbersSyncStarManyYields(int limit) sync* {
int i = 0;
final int blockLimit = limit - (limit % (20 * 7));
while (i < blockLimit) {
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
}
while (i < limit) {
yield i++;
}
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Stream<int> generateNumbersAsyncStarManyYields(int limit) async* {
int i = 0;
final int blockLimit = limit - (limit % (20 * 7));
while (i < blockLimit) {
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
yield i++;
}
while (i < limit) {
yield i++;
}
}
class Target {
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
FutureOr<int> returnFutureOr(int i) => i;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> returnFuture(int i) => Future.value(i);
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> returnAsync(int i) async => i;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
int returnSync(int i) => i;
}
class Target2 extends Target {
@override
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
FutureOr<int> returnFutureOr(int i) => i;
@override
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> returnFuture(int i) => Future.value(i);
@override
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> returnAsync(int i) async => i;
@override
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
int returnSync(int i) => i;
}
class Target3 extends Target {
@override
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
FutureOr<int> returnFutureOr(int i) => i;
@override
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> returnFuture(int i) => Future.value(i);
@override
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Future<int> returnAsync(int i) async => i;
@override
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
int returnSync(int i) => i;
}
typedef PerformSyncCallsFunction = int Function();
typedef PerformAsyncCallsFunction = Future<int> Function();
class SyncCallBenchmark {
final String name;
final PerformSyncCallsFunction performCalls;
SyncCallBenchmark(this.name, this.performCalls);
// Returns the number of nanoseconds per call.
double measureFor(Duration duration) {
final sw = Stopwatch()..start();
final durationInMicroseconds = duration.inMicroseconds;
int numberOfCalls = 0;
int totalMicroseconds = 0;
do {
numberOfCalls += performCalls();
totalMicroseconds = sw.elapsedMicroseconds;
} while (totalMicroseconds < durationInMicroseconds);
final int totalNanoseconds = sw.elapsed.inMicroseconds * 1000;
return totalNanoseconds / numberOfCalls;
}
// Runs warmup phase, runs benchmark and reports result.
void report() {
// Warmup for 100 ms.
measureFor(const Duration(milliseconds: 100));
// Run benchmark for 2 seconds.
final double nsPerCall = measureFor(const Duration(seconds: 2));
// Report result.
print('$name(RunTimeRaw): $nsPerCall ns.');
}
}
class AsyncCallBenchmark {
final String name;
final PerformAsyncCallsFunction performCalls;
AsyncCallBenchmark(this.name, this.performCalls);
// Returns the number of nanoseconds per call.
Future<double> measureFor(Duration duration) async {
final sw = Stopwatch()..start();
final durationInMicroseconds = duration.inMicroseconds;
int numberOfCalls = 0;
int totalMicroseconds = 0;
do {
numberOfCalls += await performCalls();
totalMicroseconds = sw.elapsedMicroseconds;
} while (totalMicroseconds < durationInMicroseconds);
final int totalNanoseconds = sw.elapsed.inMicroseconds * 1000;
return totalNanoseconds / numberOfCalls;
}
// Runs warmup phase, runs benchmark and reports result.
Future report() async {
// Warmup for 100 ms.
await measureFor(const Duration(milliseconds: 100));
// Run benchmark for 2 seconds.
final double nsPerCall = await measureFor(const Duration(seconds: 2));
// Report result.
print('$name(RunTimeRaw): $nsPerCall ns.');
}
}
@@ -1,23 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:io';
import 'package:benchmark_harness/benchmark_harness.dart';
class DartCLIStartup extends BenchmarkBase {
const DartCLIStartup() : super('DartCLIStartup');
// The benchmark code.
@override
void run() {
Process.runSync(Platform.executable, ['help']);
}
}
void main() {
const DartCLIStartup().report();
}
-515
View File
@@ -1,515 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
// This benchmark suite measures the overhead of dynamically calling functions
// and closures by calling a set of functions and closures, testing non-dynamic
// calls, calls after casting the function tearoff or closure to dynamic, and
// similarly defined functions and closures except that the parameters and
// return types are all dynamic.
// @dart=2.9
import 'package:benchmark_harness/benchmark_harness.dart';
const int kRepeat = 100;
void main() {
const NonDynamicFunction().report();
const NonDynamicFunctionOptSkipped().report();
const NonDynamicFunctionOptProvided().report();
const NonDynamicFunctionNamedSkipped().report();
const NonDynamicFunctionNamedProvided().report();
const NonDynamicClosure().report();
const NonDynamicClosureOptSkipped().report();
const NonDynamicClosureOptProvided().report();
const NonDynamicClosureNamedSkipped().report();
const NonDynamicClosureNamedProvided().report();
const DynamicCastFunction().report();
const DynamicCastFunctionOptSkipped().report();
const DynamicCastFunctionOptProvided().report();
const DynamicCastFunctionNamedSkipped().report();
const DynamicCastFunctionNamedProvided().report();
const DynamicCastClosure().report();
const DynamicCastClosureOptSkipped().report();
const DynamicCastClosureOptProvided().report();
const DynamicCastClosureNamedSkipped().report();
const DynamicCastClosureNamedProvided().report();
const DynamicDefFunction().report();
const DynamicDefFunctionOptSkipped().report();
const DynamicDefFunctionOptProvided().report();
const DynamicDefFunctionNamedSkipped().report();
const DynamicDefFunctionNamedProvided().report();
const DynamicDefClosure().report();
const DynamicDefClosureOptSkipped().report();
const DynamicDefClosureOptProvided().report();
const DynamicDefClosureNamedSkipped().report();
const DynamicDefClosureNamedProvided().report();
const DynamicClassASingleton().report();
const DynamicClassBSingleton().report();
const DynamicClassCFresh().report();
const DynamicClassDFresh().report();
}
@pragma('vm:never-inline')
void f1(String s) {}
@pragma('vm:never-inline')
Function(String) c1 = (String s) => {};
@pragma('vm:never-inline')
void f2(String s, [String t = 'default']) {}
@pragma('vm:never-inline')
Function(String, [String]) c2 = (String s, [String t = 'default']) => {};
@pragma('vm:never-inline')
void f3(String s, {String t = 'default'}) {}
@pragma('vm:never-inline')
Function(String, {String t}) c3 = (String s, {String t = 'default'}) => {};
@pragma('vm:never-inline')
dynamic df1 = f1 as dynamic;
@pragma('vm:never-inline')
dynamic dc1 = c1 as dynamic;
@pragma('vm:never-inline')
dynamic df2 = f2 as dynamic;
@pragma('vm:never-inline')
dynamic dc2 = c2 as dynamic;
@pragma('vm:never-inline')
dynamic df3 = f3 as dynamic;
@pragma('vm:never-inline')
dynamic dc3 = c3 as dynamic;
@pragma('vm:never-inline')
dynamic df1NonCast(dynamic s) {}
@pragma('vm:never-inline')
Function dc1NonCast = (dynamic s) => {};
@pragma('vm:never-inline')
dynamic df2NonCast(dynamic s, [dynamic t = 'default']) {}
@pragma('vm:never-inline')
Function dc2NonCast = (dynamic s, [dynamic t = 'default']) => {};
@pragma('vm:never-inline')
dynamic df3NonCast(dynamic s, {dynamic t = 'default'}) {}
@pragma('vm:never-inline')
Function dc3NonCast = (dynamic s, {dynamic t = 'default'}) => {};
class A {
const A();
}
class B extends A {
const B();
}
@pragma('vm:never-inline')
dynamic k = (A a) {};
class C {
C();
}
class D extends C {
D();
}
@pragma('vm:never-inline')
dynamic j = (C c) {};
class NonDynamicFunction extends BenchmarkBase {
const NonDynamicFunction() : super('Dynamic.NonDynamicFunction');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
f1('');
}
}
}
class NonDynamicClosure extends BenchmarkBase {
const NonDynamicClosure() : super('Dynamic.NonDynamicClosure');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
c1('');
}
}
}
class NonDynamicFunctionOptSkipped extends BenchmarkBase {
const NonDynamicFunctionOptSkipped()
: super('Dynamic.NonDynamicFunctionOptSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
f2('');
}
}
}
class NonDynamicFunctionOptProvided extends BenchmarkBase {
const NonDynamicFunctionOptProvided()
: super('Dynamic.NonDynamicFunctionOptProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
f2('', '');
}
}
}
class NonDynamicFunctionNamedSkipped extends BenchmarkBase {
const NonDynamicFunctionNamedSkipped()
: super('Dynamic.NonDynamicFunctionNamedSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
f3('');
}
}
}
class NonDynamicFunctionNamedProvided extends BenchmarkBase {
const NonDynamicFunctionNamedProvided()
: super('Dynamic.NonDynamicFunctionNamedProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
f3('', t: '');
}
}
}
class NonDynamicClosureOptSkipped extends BenchmarkBase {
const NonDynamicClosureOptSkipped()
: super('Dynamic.NonDynamicClosureOptSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
c2('');
}
}
}
class NonDynamicClosureOptProvided extends BenchmarkBase {
const NonDynamicClosureOptProvided()
: super('Dynamic.NonDynamicClosureOptProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
c2('', '');
}
}
}
class NonDynamicClosureNamedSkipped extends BenchmarkBase {
const NonDynamicClosureNamedSkipped()
: super('Dynamic.NonDynamicClosureNamedSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
c3('');
}
}
}
class NonDynamicClosureNamedProvided extends BenchmarkBase {
const NonDynamicClosureNamedProvided()
: super('Dynamic.NonDynamicClosureNamedProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
c3('', t: '');
}
}
}
class DynamicCastFunction extends BenchmarkBase {
const DynamicCastFunction() : super('Dynamic.DynamicCastFunction');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df1('');
}
}
}
class DynamicCastClosure extends BenchmarkBase {
const DynamicCastClosure() : super('Dynamic.DynamicCastClosure');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc1('');
}
}
}
class DynamicCastFunctionOptSkipped extends BenchmarkBase {
const DynamicCastFunctionOptSkipped()
: super('Dynamic.DynamicCastFunctionOptSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df2('');
}
}
}
class DynamicCastFunctionOptProvided extends BenchmarkBase {
const DynamicCastFunctionOptProvided()
: super('Dynamic.DynamicCastFunctionOptProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df2('', '');
}
}
}
class DynamicCastFunctionNamedSkipped extends BenchmarkBase {
const DynamicCastFunctionNamedSkipped()
: super('Dynamic.DynamicCastFunctionNamedSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df3('');
}
}
}
class DynamicCastFunctionNamedProvided extends BenchmarkBase {
const DynamicCastFunctionNamedProvided()
: super('Dynamic.DynamicCastFunctionNamedProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df3('', t: '');
}
}
}
class DynamicCastClosureOptSkipped extends BenchmarkBase {
const DynamicCastClosureOptSkipped()
: super('Dynamic.DynamicCastClosureOptSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc2('');
}
}
}
class DynamicCastClosureOptProvided extends BenchmarkBase {
const DynamicCastClosureOptProvided()
: super('Dynamic.DynamicCastClosureOptProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc2('', '');
}
}
}
class DynamicCastClosureNamedSkipped extends BenchmarkBase {
const DynamicCastClosureNamedSkipped()
: super('Dynamic.DynamicCastClosureNamedSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc3('');
}
}
}
class DynamicCastClosureNamedProvided extends BenchmarkBase {
const DynamicCastClosureNamedProvided()
: super('Dynamic.DynamicCastClosureNamedProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc3('', t: '');
}
}
}
class DynamicDefFunction extends BenchmarkBase {
const DynamicDefFunction() : super('Dynamic.DynamicDefFunction');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df1NonCast('');
}
}
}
class DynamicDefClosure extends BenchmarkBase {
const DynamicDefClosure() : super('Dynamic.DynamicDefClosure');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc1NonCast('');
}
}
}
class DynamicDefFunctionOptSkipped extends BenchmarkBase {
const DynamicDefFunctionOptSkipped()
: super('Dynamic.DynamicDefFunctionOptSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df2NonCast('');
}
}
}
class DynamicDefFunctionOptProvided extends BenchmarkBase {
const DynamicDefFunctionOptProvided()
: super('Dynamic.DynamicDefFunctionOptProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df2NonCast('', '');
}
}
}
class DynamicDefFunctionNamedSkipped extends BenchmarkBase {
const DynamicDefFunctionNamedSkipped()
: super('Dynamic.DynamicDefFunctionNamedSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df3NonCast('');
}
}
}
class DynamicDefFunctionNamedProvided extends BenchmarkBase {
const DynamicDefFunctionNamedProvided()
: super('Dynamic.DynamicDefFunctionNamedProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df3NonCast('', t: '');
}
}
}
class DynamicDefClosureOptSkipped extends BenchmarkBase {
const DynamicDefClosureOptSkipped()
: super('Dynamic.DynamicDefClosureOptSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc2NonCast('');
}
}
}
class DynamicDefClosureOptProvided extends BenchmarkBase {
const DynamicDefClosureOptProvided()
: super('Dynamic.DynamicDefClosureOptProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc2NonCast('', '');
}
}
}
class DynamicDefClosureNamedSkipped extends BenchmarkBase {
const DynamicDefClosureNamedSkipped()
: super('Dynamic.DynamicDefClosureNamedSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc3NonCast('');
}
}
}
class DynamicDefClosureNamedProvided extends BenchmarkBase {
const DynamicDefClosureNamedProvided()
: super('Dynamic.DynamicDefClosureNamedProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc3NonCast('', t: '');
}
}
}
class DynamicClassASingleton extends BenchmarkBase {
final A a;
const DynamicClassASingleton()
: a = const A(),
super('Dynamic.DynamicClassASingleton');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
k(a);
}
}
}
class DynamicClassBSingleton extends BenchmarkBase {
final B b;
const DynamicClassBSingleton()
: b = const B(),
super('Dynamic.DynamicClassBSingleton');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
k(b);
}
}
}
class DynamicClassCFresh extends BenchmarkBase {
const DynamicClassCFresh() : super('Dynamic.DynamicClassCFresh');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
j(C());
}
}
}
class DynamicClassDFresh extends BenchmarkBase {
const DynamicClassDFresh() : super('Dynamic.DynamicClassDFresh');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
j(D());
}
}
}
@@ -1,38 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:isolate';
import 'json_benchmark.dart';
import 'latency.dart';
Future<void> main() async {
// Start GC pressure from helper isolate.
final exitPort = ReceivePort();
final exitFuture = exitPort.first;
final isolate = await Isolate.spawn(run, null, onExit: exitPort.sendPort);
// Measure event loop latency.
const tickDuration = Duration(milliseconds: 1);
const numberOfTicks = 8 * 1000; // min 8 seconds.
final EventLoopLatencyStats stats = await measureEventLoopLatency(
tickDuration,
numberOfTicks,
);
// Kill isolate & wait until it's dead.
isolate.kill(priority: Isolate.immediate);
await exitFuture;
// Report event loop latency statistics.
stats.report('EventLoopLatencyJson');
}
void run(dynamic msg) {
while (true) {
JsonRoundTripBenchmark().run();
}
}
@@ -1,49 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:math';
import 'dart:convert';
class JsonRoundTripBenchmark {
void run() {
final res = json.decode(jsonData);
final out = json.encode(res);
if (out[0] != jsonData[0]) {
throw 'json conversion error';
}
}
}
// Builds around 4.5 MB of json data - big enough so the decoded object graph
// does not fit into new space.
final String jsonData = () {
final rnd = Random(42);
dynamic buildTree(int depth) {
final int coin = rnd.nextInt(1000);
if (depth == 0) {
if (coin % 2 == 0) return coin;
return 'foo-$coin';
}
if (coin % 2 == 0) {
final map = <String, dynamic>{};
final int length = rnd.nextInt(18);
for (int i = 0; i < length; ++i) {
map['bar-$i'] = buildTree(depth - 1);
}
return map;
} else {
final list = <dynamic>[];
final int length = rnd.nextInt(18);
for (int i = 0; i < length; ++i) {
list.add(buildTree(depth - 1));
}
return list;
}
}
return json.encode({'data': buildTree(6)});
}();
@@ -1,141 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:async';
import 'dart:io';
import 'dart:math' as math;
import 'dart:typed_data';
/// Measures event loop responsiveness.
///
/// Schedules new timer events, [tickDuration] in the future, and measures how
/// long it takes for these events to actually arrive.
///
/// Runs [numberOfTicks] times before completing with [EventLoopLatencyStats].
Future<EventLoopLatencyStats> measureEventLoopLatency(
Duration tickDuration,
int numberOfTicks,
) {
final completer = Completer<EventLoopLatencyStats>();
final tickDurationInUs = tickDuration.inMicroseconds;
final buffer = _TickLatencies(numberOfTicks);
final sw = Stopwatch()..start();
int lastTimestamp = 0;
void trigger() {
final int currentTimestamp = sw.elapsedMicroseconds;
// Every tick we missed to schedule we'll add with difference to when we
// would've scheduled it and when we became responsive again.
bool done = false;
while (!done && lastTimestamp < (currentTimestamp - tickDurationInUs)) {
done = !buffer.add(currentTimestamp - lastTimestamp - tickDurationInUs);
lastTimestamp += tickDurationInUs;
}
if (!done) {
lastTimestamp = currentTimestamp;
Timer(tickDuration, trigger);
} else {
completer.complete(buffer.makeStats());
}
}
Timer(tickDuration, trigger);
return completer.future;
}
/// Result of the event loop latency measurement.
class EventLoopLatencyStats {
/// Minimum latency between scheduling a tick and it's arrival (in ms).
final double minLatency;
/// Average latency between scheduling a tick and it's arrival (in ms).
final double avgLatency;
/// Maximum latency between scheduling a tick and it's arrival (in ms).
final double maxLatency;
/// The 50th percentile (median) (in ms).
final double percentile50th;
/// The 90th percentile (in ms).
final double percentile90th;
/// The 95th percentile (in ms).
final double percentile95th;
/// The 99th percentile (in ms).
final double percentile99th;
/// The maximum RSS of the process.
final int maxRss;
EventLoopLatencyStats(
this.minLatency,
this.avgLatency,
this.maxLatency,
this.percentile50th,
this.percentile90th,
this.percentile95th,
this.percentile99th,
this.maxRss,
);
void report(String name) {
print('$name.Min(RunTimeRaw): $minLatency ms.');
print('$name.Avg(RunTimeRaw): $avgLatency ms.');
print('$name.Percentile50(RunTimeRaw): $percentile50th ms.');
print('$name.Percentile90(RunTimeRaw): $percentile90th ms.');
print('$name.Percentile95(RunTimeRaw): $percentile95th ms.');
print('$name.Percentile99(RunTimeRaw): $percentile99th ms.');
print('$name.Max(RunTimeRaw): $maxLatency ms.');
print('$name.MaxRss(MemoryUse): $maxRss');
}
}
/// Accumulates tick latencies and makes statistics for it.
class _TickLatencies {
final Uint64List _timestamps;
int _index = 0;
_TickLatencies(int numberOfTicks) : _timestamps = Uint64List(numberOfTicks);
/// Returns `true` while the buffer has not been filled yet.
bool add(int latencyInUs) {
_timestamps[_index++] = latencyInUs;
return _index < _timestamps.length;
}
EventLoopLatencyStats makeStats() {
if (_index != _timestamps.length) {
throw 'Buffer has not been fully filled yet.';
}
_timestamps.sort();
final length = _timestamps.length;
final double avg = _timestamps.fold(0, (int a, int b) => a + b) / length;
final int min = _timestamps.fold(0x7fffffffffffffff, math.min);
final int max = _timestamps.fold(0, math.max);
final percentile50th = _timestamps[50 * length ~/ 100];
final percentile90th = _timestamps[90 * length ~/ 100];
final percentile95th = _timestamps[95 * length ~/ 100];
final percentile99th = _timestamps[99 * length ~/ 100];
return EventLoopLatencyStats(
min / 1000,
avg / 1000,
max / 1000,
percentile50th / 1000,
percentile90th / 1000,
percentile95th / 1000,
percentile99th / 1000,
ProcessInfo.maxRss,
);
}
}
@@ -1,38 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:isolate';
import 'json_benchmark.dart';
import 'latency.dart';
main() async {
// Start GC pressure from helper isolate.
final exitPort = ReceivePort();
final exitFuture = exitPort.first;
final isolate = await Isolate.spawn(run, null, onExit: exitPort.sendPort);
// Measure event loop latency.
const tickDuration = const Duration(milliseconds: 1);
const numberOfTicks = 8 * 1000; // min 8 seconds.
final EventLoopLatencyStats stats = await measureEventLoopLatency(
tickDuration,
numberOfTicks,
);
// Kill isolate & wait until it's dead.
isolate.kill(priority: Isolate.immediate);
await exitFuture;
// Report event loop latency statistics.
stats.report('EventLoopLatencyJson350KB');
}
void run(dynamic msg) {
while (true) {
JsonRoundTripBenchmark().run();
}
}
@@ -1,49 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:math';
import 'dart:convert';
class JsonRoundTripBenchmark {
void run() {
final res = json.decode(jsonData);
final out = json.encode(res);
if (out[0] != jsonData[0]) {
throw 'json conversion error';
}
}
}
// Builds around 350 KB of json data - small enough so the decoded object graph
// fits into new space.
final String jsonData = () {
final rnd = Random(42);
dynamic buildTree(int depth) {
final int coin = rnd.nextInt(1000);
if (depth == 0) {
if (coin % 2 == 0) return coin;
return 'foo-$coin';
}
if (coin % 2 == 0) {
final map = <String, dynamic>{};
final int length = rnd.nextInt(19);
for (int i = 0; i < length; ++i) {
map['bar-$i'] = buildTree(depth - 1);
}
return map;
} else {
final list = <dynamic>[];
final int length = rnd.nextInt(18);
for (int i = 0; i < length; ++i) {
list.add(buildTree(depth - 1));
}
return list;
}
}
return json.encode({'data': buildTree(5)});
}();
@@ -1,141 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:async';
import 'dart:io';
import 'dart:math' as math;
import 'dart:typed_data';
/// Measures event loop responsiveness.
///
/// Schedules new timer events, [tickDuration] in the future, and measures how
/// long it takes for these events to actually arrive.
///
/// Runs [numberOfTicks] times before completing with [EventLoopLatencyStats].
Future<EventLoopLatencyStats> measureEventLoopLatency(
Duration tickDuration,
int numberOfTicks,
) {
final completer = Completer<EventLoopLatencyStats>();
final tickDurationInUs = tickDuration.inMicroseconds;
final buffer = _TickLatencies(numberOfTicks);
final sw = Stopwatch()..start();
int lastTimestamp = 0;
void trigger() {
final int currentTimestamp = sw.elapsedMicroseconds;
// Every tick we missed to schedule we'll add with difference to when we
// would've scheduled it and when we became responsive again.
bool done = false;
while (!done && lastTimestamp < (currentTimestamp - tickDurationInUs)) {
done = !buffer.add(currentTimestamp - lastTimestamp - tickDurationInUs);
lastTimestamp += tickDurationInUs;
}
if (!done) {
lastTimestamp = currentTimestamp;
Timer(tickDuration, trigger);
} else {
completer.complete(buffer.makeStats());
}
}
Timer(tickDuration, trigger);
return completer.future;
}
/// Result of the event loop latency measurement.
class EventLoopLatencyStats {
/// Minimum latency between scheduling a tick and it's arrival (in ms).
final double minLatency;
/// Average latency between scheduling a tick and it's arrival (in ms).
final double avgLatency;
/// Maximum latency between scheduling a tick and it's arrival (in ms).
final double maxLatency;
/// The 50th percentile (median) (in ms).
final double percentile50th;
/// The 90th percentile (in ms).
final double percentile90th;
/// The 95th percentile (in ms).
final double percentile95th;
/// The 99th percentile (in ms).
final double percentile99th;
/// The maximum RSS of the process.
final int maxRss;
EventLoopLatencyStats(
this.minLatency,
this.avgLatency,
this.maxLatency,
this.percentile50th,
this.percentile90th,
this.percentile95th,
this.percentile99th,
this.maxRss,
);
void report(String name) {
print('$name.Min(RunTimeRaw): $minLatency ms.');
print('$name.Avg(RunTimeRaw): $avgLatency ms.');
print('$name.Percentile50(RunTimeRaw): $percentile50th ms.');
print('$name.Percentile90(RunTimeRaw): $percentile90th ms.');
print('$name.Percentile95(RunTimeRaw): $percentile95th ms.');
print('$name.Percentile99(RunTimeRaw): $percentile99th ms.');
print('$name.Max(RunTimeRaw): $maxLatency ms.');
print('$name.MaxRss(MemoryUse): $maxRss');
}
}
/// Accumulates tick latencies and makes statistics for it.
class _TickLatencies {
final Uint64List _timestamps;
int _index = 0;
_TickLatencies(int numberOfTicks) : _timestamps = Uint64List(numberOfTicks);
/// Returns `true` while the buffer has not been filled yet.
bool add(int latencyInUs) {
_timestamps[_index++] = latencyInUs;
return _index < _timestamps.length;
}
EventLoopLatencyStats makeStats() {
if (_index != _timestamps.length) {
throw 'Buffer has not been fully filled yet.';
}
_timestamps.sort();
final length = _timestamps.length;
final double avg = _timestamps.fold(0, (int a, int b) => a + b) / length;
final int min = _timestamps.fold(0x7fffffffffffffff, math.min);
final int max = _timestamps.fold(0, math.max);
final percentile50th = _timestamps[50 * length ~/ 100];
final percentile90th = _timestamps[90 * length ~/ 100];
final percentile95th = _timestamps[95 * length ~/ 100];
final percentile99th = _timestamps[99 * length ~/ 100];
return EventLoopLatencyStats(
min / 1000,
avg / 1000,
max / 1000,
percentile50th / 1000,
percentile90th / 1000,
percentile95th / 1000,
percentile99th / 1000,
ProcessInfo.maxRss,
);
}
}
@@ -1,37 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:isolate';
import 'regexp_benchmark.dart';
import 'latency.dart';
main() async {
final exitPort = ReceivePort();
final exitFuture = exitPort.first;
final isolate = await Isolate.spawn(run, null, onExit: exitPort.sendPort);
// Measure event loop latency.
const tickDuration = const Duration(milliseconds: 1);
const numberOfTicks = 8 * 1000; // min 8 seconds.
final EventLoopLatencyStats stats = await measureEventLoopLatency(
tickDuration,
numberOfTicks,
);
// Kill isolate & wait until it's dead.
isolate.kill(priority: Isolate.immediate);
await exitFuture;
// Report event loop latency statistics.
stats.report('EventLoopLatencyRegexp');
}
void run(dynamic msg) {
while (true) {
RegexpBenchmark().run();
}
}
@@ -1,141 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:async';
import 'dart:io';
import 'dart:math' as math;
import 'dart:typed_data';
/// Measures event loop responsiveness.
///
/// Schedules new timer events, [tickDuration] in the future, and measures how
/// long it takes for these events to actually arrive.
///
/// Runs [numberOfTicks] times before completing with [EventLoopLatencyStats].
Future<EventLoopLatencyStats> measureEventLoopLatency(
Duration tickDuration,
int numberOfTicks,
) {
final completer = Completer<EventLoopLatencyStats>();
final tickDurationInUs = tickDuration.inMicroseconds;
final buffer = _TickLatencies(numberOfTicks);
final sw = Stopwatch()..start();
int lastTimestamp = 0;
void trigger() {
final int currentTimestamp = sw.elapsedMicroseconds;
// Every tick we missed to schedule we'll add with difference to when we
// would've scheduled it and when we became responsive again.
bool done = false;
while (!done && lastTimestamp < (currentTimestamp - tickDurationInUs)) {
done = !buffer.add(currentTimestamp - lastTimestamp - tickDurationInUs);
lastTimestamp += tickDurationInUs;
}
if (!done) {
lastTimestamp = currentTimestamp;
Timer(tickDuration, trigger);
} else {
completer.complete(buffer.makeStats());
}
}
Timer(tickDuration, trigger);
return completer.future;
}
/// Result of the event loop latency measurement.
class EventLoopLatencyStats {
/// Minimum latency between scheduling a tick and it's arrival (in ms).
final double minLatency;
/// Average latency between scheduling a tick and it's arrival (in ms).
final double avgLatency;
/// Maximum latency between scheduling a tick and it's arrival (in ms).
final double maxLatency;
/// The 50th percentile (median) (in ms).
final double percentile50th;
/// The 90th percentile (in ms).
final double percentile90th;
/// The 95th percentile (in ms).
final double percentile95th;
/// The 99th percentile (in ms).
final double percentile99th;
/// The maximum RSS of the process.
final int maxRss;
EventLoopLatencyStats(
this.minLatency,
this.avgLatency,
this.maxLatency,
this.percentile50th,
this.percentile90th,
this.percentile95th,
this.percentile99th,
this.maxRss,
);
void report(String name) {
print('$name.Min(RunTimeRaw): $minLatency ms.');
print('$name.Avg(RunTimeRaw): $avgLatency ms.');
print('$name.Percentile50(RunTimeRaw): $percentile50th ms.');
print('$name.Percentile90(RunTimeRaw): $percentile90th ms.');
print('$name.Percentile95(RunTimeRaw): $percentile95th ms.');
print('$name.Percentile99(RunTimeRaw): $percentile99th ms.');
print('$name.Max(RunTimeRaw): $maxLatency ms.');
print('$name.MaxRss(MemoryUse): $maxRss');
}
}
/// Accumulates tick latencies and makes statistics for it.
class _TickLatencies {
final Uint64List _timestamps;
int _index = 0;
_TickLatencies(int numberOfTicks) : _timestamps = Uint64List(numberOfTicks);
/// Returns `true` while the buffer has not been filled yet.
bool add(int latencyInUs) {
_timestamps[_index++] = latencyInUs;
return _index < _timestamps.length;
}
EventLoopLatencyStats makeStats() {
if (_index != _timestamps.length) {
throw 'Buffer has not been fully filled yet.';
}
_timestamps.sort();
final length = _timestamps.length;
final double avg = _timestamps.fold(0, (int a, int b) => a + b) / length;
final int min = _timestamps.fold(0x7fffffffffffffff, math.min);
final int max = _timestamps.fold(0, math.max);
final percentile50th = _timestamps[50 * length ~/ 100];
final percentile90th = _timestamps[90 * length ~/ 100];
final percentile95th = _timestamps[95 * length ~/ 100];
final percentile99th = _timestamps[99 * length ~/ 100];
return EventLoopLatencyStats(
min / 1000,
avg / 1000,
max / 1000,
percentile50th / 1000,
percentile90th / 1000,
percentile95th / 1000,
percentile99th / 1000,
ProcessInfo.maxRss,
);
}
}
@@ -1,16 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:math';
import 'dart:convert';
class RegexpBenchmark {
void run() {
final re = RegExp(r'(x+)*y');
final s = 'x' * 26 + '';
re.allMatches(s).iterator.moveNext();
}
}
-27
View File
@@ -1,27 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'package:benchmark_harness/benchmark_harness.dart';
class Example extends BenchmarkBase {
const Example() : super('Example');
// The benchmark code.
@override
void run() {}
// Not measured setup code executed prior to the benchmark runs.
@override
void setup() {}
// Not measured teardown code executed after the benchmark runs.
@override
void teardown() {}
}
void main() {
const Example().report();
}
-126
View File
@@ -1,126 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Micro-benchmark for ffi struct field stores and loads.
//
// Only tests a single field because the FfiMemory benchmark already tests loads
// and stores of different field sizes.
// @dart=2.9
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'package:benchmark_harness/benchmark_harness.dart';
//
// Struct field store (plus Pointer elementAt and load).
//
void doStoreInt32(Pointer<VeryLargeStruct> pointer, int length) {
for (int i = 0; i < length; i++) {
pointer[i].c = 1;
}
}
//
// Struct field load (plus Pointer elementAt and load).
//
int doLoadInt32(Pointer<VeryLargeStruct> pointer, int length) {
int x = 0;
for (int i = 0; i < length; i++) {
x += pointer[i].c;
}
return x;
}
//
// Benchmark fixture.
//
// Number of repeats: 1000
// * CPU: Intel(R) Xeon(R) Gold 6154
// * Architecture: x64
// * 150000 - 465000 us (without optimizations)
// * 14 - ??? us (expected with optimizations, on par with typed data)
const N = 1000;
class FieldLoadStore extends BenchmarkBase {
Pointer<VeryLargeStruct> pointer;
FieldLoadStore() : super('FfiStruct.FieldLoadStore');
@override
void setup() => pointer = calloc(N);
@override
void teardown() => calloc.free(pointer);
@override
void run() {
doStoreInt32(pointer, N);
final int x = doLoadInt32(pointer, N);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
//
// Main driver.
//
void main() {
final benchmarks = [() => FieldLoadStore()];
for (final benchmark in benchmarks) {
benchmark().report();
}
}
//
// Test struct.
//
class VeryLargeStruct extends Struct {
@Int8()
int a;
@Int16()
int b;
@Int32()
int c;
@Int64()
int d;
@Uint8()
int e;
@Uint16()
int f;
@Uint32()
int g;
@Uint64()
int h;
@IntPtr()
int i;
@Double()
double j;
@Float()
double k;
Pointer<VeryLargeStruct> parent;
@IntPtr()
int numChildren;
Pointer<VeryLargeStruct> children;
@Int8()
int smallLastField;
}
@@ -1,27 +0,0 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'package:benchmark_harness/benchmark_harness.dart';
class IterationBenchmark extends BenchmarkBase {
List<int> list = List.generate(1000, (i) => i);
var r = 0;
void fn(int i) => r = 123 * i;
IterationBenchmark(name) : super(name);
}
class ForEach extends IterationBenchmark {
ForEach() : super('ForEachLoop');
@override
void run() {
list.forEach(fn);
}
}
void main() {
ForEach().report();
}
@@ -1,35 +0,0 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'package:benchmark_harness/benchmark_harness.dart';
class IterationBenchmark extends BenchmarkBase {
List<int> list = List.generate(1000, (i) => i);
var r = 0;
void fn(int i) => r = 123 * i;
IterationBenchmark(name) : super(name);
}
Iterable<int> generateElements(List<int> list) sync* {
for (var i = 0; i < list.length; i++) {
yield list[i];
}
}
class ForInGenerated extends IterationBenchmark {
ForInGenerated() : super('ForInGeneratedLoop');
@override
void run() {
for (var item in generateElements(list)) {
fn(item);
}
}
}
void main() {
ForInGenerated().report();
}
-29
View File
@@ -1,29 +0,0 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'package:benchmark_harness/benchmark_harness.dart';
class IterationBenchmark extends BenchmarkBase {
List<int> list = List.generate(1000, (i) => i);
var r = 0;
void fn(int i) => r = 123 * i;
IterationBenchmark(name) : super(name);
}
class ForIn extends IterationBenchmark {
ForIn() : super('ForInLoop');
@override
void run() {
for (var item in list) {
fn(item);
}
}
}
void main() {
ForIn().report();
}
-29
View File
@@ -1,29 +0,0 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'package:benchmark_harness/benchmark_harness.dart';
class IterationBenchmark extends BenchmarkBase {
List<int> list = List.generate(1000, (i) => i);
var r = 0;
void fn(int i) => r = 123 * i;
IterationBenchmark(name) : super(name);
}
class ForLoop extends IterationBenchmark {
ForLoop() : super('ForLoop');
@override
void run() {
for (var i = 0; i < list.length; i++) {
fn(list[i]);
}
}
}
void main() {
ForLoop().report();
}
File diff suppressed because it is too large Load Diff
@@ -1,48 +0,0 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Benchmark for https://github.com/dart-lang/sdk/issues/48641.
//
// Measures the average time needed for a lookup in Sets of integers.
// @dart=2.9
import 'dart:math';
import 'dart:collection';
import 'package:benchmark_harness/benchmark_harness.dart';
class SetBenchmark extends BenchmarkBase {
SetBenchmark(String name, this.mySet) : super(name);
final Set<int> mySet;
@override
void run() {
mySet.contains(123456789);
}
}
void main() {
final list = [
for (int i = 0; i < 14790; i++) (i + 1) * 0x10000000 + 123456789,
];
final r = Random();
final randomList = List<int>.generate(14790, (_) => r.nextInt(1 << 31));
final benchmarks = [
() => SetBenchmark("IntegerSetLookup.DefaultHashSet", {...list}),
() =>
SetBenchmark("IntegerSetLookup.HashSet", HashSet<int>()..addAll(list)),
() =>
SetBenchmark("IntegerSetLookup.DefaultHashSet_Random", {...randomList}),
() => SetBenchmark(
"IntegerSetLookup.HashSet_Random",
HashSet<int>()..addAll(randomList),
),
];
for (final benchmark in benchmarks) {
benchmark().report();
}
}
-153
View File
@@ -1,153 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:async';
import 'dart:isolate';
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:meta/meta.dart';
class SendReceiveBytes extends AsyncBenchmarkBase {
SendReceiveBytes(
String name, {
@required this.size,
@required this.useTransferable,
}) : super(name);
@override
Future<void> run() async {
await helper.run();
}
@override
Future<void> setup() async {
helper = SendReceiveHelper(size, useTransferable: useTransferable);
await helper.setup();
}
@override
Future<void> teardown() async {
await helper.finalize();
}
final bool useTransferable;
final int size;
SendReceiveHelper helper;
}
class StartMessage {
final SendPort sendPort;
final bool useTransferable;
final int size;
StartMessage(this.sendPort, this.useTransferable, this.size);
}
// Measures how long sending and receiving of [size]-length Uint8List takes.
class SendReceiveHelper {
SendReceiveHelper(this.size, {@required this.useTransferable});
Future<void> setup() async {
data = Uint8List(size);
port = ReceivePort();
inbox = StreamIterator<dynamic>(port);
workerCompleted = Completer<bool>();
workerExitedPort =
ReceivePort()..listen((_) => workerCompleted.complete(true));
worker = await Isolate.spawn(
isolate,
StartMessage(port.sendPort, useTransferable, size),
onExit: workerExitedPort.sendPort,
);
await inbox.moveNext();
outbox = inbox.current;
}
Future<void> finalize() async {
outbox.send(null);
await workerCompleted.future;
workerExitedPort.close();
port.close();
}
// Send data to worker, wait for an answer.
Future<void> run() async {
outbox.send(packageList(data, useTransferable));
await inbox.moveNext();
final received = inbox.current;
if (useTransferable) {
final TransferableTypedData transferable = received;
transferable.materialize();
}
}
Uint8List data;
ReceivePort port;
StreamIterator<dynamic> inbox;
SendPort outbox;
Isolate worker;
Completer<bool> workerCompleted;
ReceivePort workerExitedPort;
final int size;
final bool useTransferable;
}
Object packageList(Uint8List data, bool useTransferable) =>
useTransferable ? TransferableTypedData.fromList(<Uint8List>[data]) : data;
Future<void> isolate(StartMessage startMessage) async {
final port = ReceivePort();
final inbox = StreamIterator<dynamic>(port);
final data = Uint8List.view(Uint8List(startMessage.size).buffer);
startMessage.sendPort.send(port.sendPort);
while (true) {
await inbox.moveNext();
final received = inbox.current;
if (received == null) {
break;
}
if (startMessage.useTransferable) {
final TransferableTypedData transferable = received;
transferable.materialize();
}
startMessage.sendPort.send(packageList(data, startMessage.useTransferable));
}
port.close();
}
class SizeName {
const SizeName(this.size, this.name);
final int size;
final String name;
}
const List<SizeName> sizes = <SizeName>[
SizeName(1 * 1024, '1KB'),
SizeName(10 * 1024, '10KB'),
SizeName(100 * 1024, '100KB'),
SizeName(1 * 1024 * 1024, '1MB'),
SizeName(10 * 1024 * 1024, '10MB'),
SizeName(100 * 1024 * 1024, '100MB'),
];
Future<void> main() async {
for (final sizeName in sizes) {
await SendReceiveBytes(
'Isolate.SendReceiveBytes${sizeName.name}',
size: sizeName.size,
useTransferable: false,
).report();
await SendReceiveBytes(
'Isolate.SendReceiveBytesTransferable${sizeName.name}',
size: sizeName.size,
useTransferable: true,
).report();
}
}
@@ -1,66 +0,0 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
const int count = 10000;
// The benchmark will spawn a long chain of isolates, keeping all of them
// alive until the last one which measures Rss at that point (i.e. when all
// isolates are alive), thereby getting a good estimate of memory-overhead per
// isolate.
void main() async {
final onDone = ReceivePort();
final lastIsolatePort = ReceivePort();
final startRss = ProcessInfo.currentRss;
final startUs = DateTime.now().microsecondsSinceEpoch;
await Isolate.spawn(
worker,
WorkerInfo(count, lastIsolatePort.sendPort),
onExit: onDone.sendPort,
);
final result = await lastIsolatePort.first as List;
final lastIsolateRss = result[0] as int;
final lastIsolateUs = result[1] as int;
await onDone.first;
final doneUs = DateTime.now().microsecondsSinceEpoch;
final averageMemoryUsageInKB = (lastIsolateRss - startRss) / count / 1024;
final averageStartLatencyInUs = (lastIsolateUs - startUs) / count;
final averageFinishLatencyInUs = (doneUs - startUs) / count;
print('IsolateBaseOverhead.Rss(MemoryUse): $averageMemoryUsageInKB');
print(
'IsolateBaseOverhead.StartLatency(Latency): $averageStartLatencyInUs us.',
);
print(
'IsolateBaseOverhead.FinishLatency(Latency): $averageFinishLatencyInUs us.',
);
}
class WorkerInfo {
final int id;
final SendPort result;
WorkerInfo(this.id, this.result);
}
Future worker(WorkerInfo workerInfo) async {
if (workerInfo.id == 1) {
workerInfo.result.send([
ProcessInfo.currentRss,
DateTime.now().microsecondsSinceEpoch,
]);
return;
}
final onExit = ReceivePort();
await Isolate.spawn(
worker,
WorkerInfo(workerInfo.id - 1, workerInfo.result),
onExit: onExit.sendPort,
);
await onExit.first;
}
@@ -1,64 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'dart:math';
import 'package:expect/expect.dart';
// Implements recursive summation via tail calls:
// fib(n) => n <= 1 ? 1
// : fib(n-1) + fib(n-2);
Future fibonacciRecursive(List args) async {
final SendPort port = args[0];
final n = args[1];
if (n <= 1) {
port.send(1);
return;
}
final left = ReceivePort();
final right = ReceivePort();
await Future.wait([
Isolate.spawn(fibonacciRecursive, [left.sendPort, n - 1]),
Isolate.spawn(fibonacciRecursive, [right.sendPort, n - 2]),
]);
final results = await Future.wait([left.first, right.first]);
port.send(results[0] + results[1]);
}
Future<void> main() async {
final rpWarmup = ReceivePort();
final rpRun = ReceivePort();
final int nWarmup = 17; // enough runs to trigger optimized compilation
final int nWarmupFactorial = 2584;
// Runs for about 8 seconds.
final int n = 21;
final int nFactorial = 17711;
final beforeRss = ProcessInfo.currentRss;
int maxRss = beforeRss;
final rssTimer = Timer.periodic(const Duration(milliseconds: 10), (_) {
maxRss = max(ProcessInfo.currentRss, maxRss);
});
final watch = Stopwatch();
watch.start();
// Warm up code by running a couple iterations in the main isolate.
await Isolate.spawn(fibonacciRecursive, [rpWarmup.sendPort, nWarmup]);
Expect.equals(nWarmupFactorial, await rpWarmup.first);
final warmup = watch.elapsedMicroseconds;
await Isolate.spawn(fibonacciRecursive, [rpRun.sendPort, n]);
Expect.equals(nFactorial, await rpRun.first);
final done = watch.elapsedMicroseconds;
print('IsolateFibonacci_$n.Calculation(RunTimeRaw): ${done - warmup} us.');
print('IsolateFibonacci_$n.DeltaPeak(MemoryUse): ${maxRss - beforeRss}');
rssTimer.cancel();
}
@@ -1,168 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart' show BenchmarkBase;
import 'package:meta/meta.dart';
class JsonDecodingBenchmark {
JsonDecodingBenchmark(
this.name, {
@required this.sample,
@required this.numTasks,
@required this.useSendAndExit,
});
Future<void> report() async {
final stopwatch = Stopwatch()..start();
// Benchmark harness counts 10 iterations as one.
for (int i = 0; i < 10; i++) {
final decodedFutures = <Future>[];
for (int i = 0; i < numTasks; i++) {
decodedFutures.add(decodeJson(useSendAndExit, sample));
}
await Future.wait(decodedFutures);
}
print('$name(RunTime): ${stopwatch.elapsedMicroseconds} us.');
}
final String name;
final Uint8List sample;
final int numTasks;
final bool useSendAndExit;
}
Uint8List createSampleJson(final size) {
final list = List.generate(size, (i) => i);
final map = <dynamic, dynamic>{};
for (int i = 0; i < size; i++) {
map['$i'] = list;
}
return utf8.encode(json.encode(map));
}
class JsonDecodeRequest {
final bool useSendAndExit;
final SendPort sendPort;
final Uint8List encodedJson;
const JsonDecodeRequest(this.useSendAndExit, this.sendPort, this.encodedJson);
}
Future<Map> decodeJson(bool useSendAndExit, Uint8List encodedJson) async {
final port = ReceivePort();
final inbox = StreamIterator<dynamic>(port);
final completer = Completer<bool>();
final workerExitedPort = RawReceivePort((v) {
completer.complete(true);
});
final workerErroredPort = RawReceivePort((v) {
stderr.writeln('worker errored out $v');
completer.completeError(true);
});
await Isolate.spawn(
jsonDecodingIsolate,
JsonDecodeRequest(useSendAndExit, port.sendPort, encodedJson),
onError: workerErroredPort.sendPort,
onExit: workerExitedPort.sendPort,
);
await completer.future;
workerExitedPort.close();
workerErroredPort.close();
await inbox.moveNext();
final decodedJson = inbox.current;
port.close();
return decodedJson;
}
Future<void> jsonDecodingIsolate(JsonDecodeRequest request) async {
final result = json.decode(utf8.decode(request.encodedJson));
if (request.useSendAndExit) {
Isolate.exit(request.sendPort, result);
} else {
request.sendPort.send(result);
}
}
class SyncJsonDecodingBenchmark extends BenchmarkBase {
SyncJsonDecodingBenchmark(
String name, {
@required this.sample,
@required this.iterations,
}) : super(name);
@override
void run() {
int l = 0;
for (int i = 0; i < iterations; i++) {
final Map map = json.decode(utf8.decode(sample));
l += map.length;
}
assert(l > 0);
}
final Uint8List sample;
final int iterations;
}
class BenchmarkConfig {
BenchmarkConfig(this.suffix, this.sample);
final String suffix;
final Uint8List sample;
}
Future<void> main() async {
final jsonString =
File('benchmarks/IsolateJson/dart2/sample.json').readAsStringSync();
final json250KB = utf8.encode(jsonString); // 294356 bytes
final decoded = json.decode(utf8.decode(json250KB));
final decoded1MB = <dynamic, dynamic>{
'1': decoded['1'],
'2': decoded['1'],
'3': decoded['1'],
'4': decoded['1'],
};
final json1MB = utf8.encode(json.encode(decoded1MB)); // 1177397 bytes
decoded['1'] = (decoded['1'] as List).sublist(0, 200);
final json100KB = utf8.encode(json.encode(decoded)); // 104685 bytes
decoded['1'] = (decoded['1'] as List).sublist(0, 100);
final json50KB = utf8.encode(json.encode(decoded)); // 51760 bytes
final configs = <BenchmarkConfig>[
BenchmarkConfig('50KB', json50KB),
BenchmarkConfig('100KB', json100KB),
BenchmarkConfig('250KB', json250KB),
BenchmarkConfig('1MB', json1MB),
];
for (final config in configs) {
for (final iterations in <int>[1, 4]) {
await JsonDecodingBenchmark(
'IsolateJson.Decode${config.suffix}x$iterations',
useSendAndExit: false,
sample: config.sample,
numTasks: iterations,
).report();
await JsonDecodingBenchmark(
'IsolateJson.SendAndExit_Decode${config.suffix}x$iterations',
useSendAndExit: true,
sample: config.sample,
numTasks: iterations,
).report();
SyncJsonDecodingBenchmark(
'IsolateJson.SyncDecode${config.suffix}x$iterations',
sample: config.sample,
iterations: iterations,
).report();
}
}
}
File diff suppressed because one or more lines are too long
@@ -1,50 +0,0 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
// This test ensures that there are no long pauses when sending large objects
// via exit/send.
// @dart=2.9
import 'dart:async';
import 'dart:typed_data';
import 'dart:math' as math;
import 'dart:isolate';
import 'latency.dart';
main() async {
final statsFuture = measureEventLoopLatency(
const Duration(milliseconds: 1),
4000,
work: () {
// Every 1 ms we allocate some objects which may trigger GC some time.
for (int i = 0; i < 32; i++) {
List.filled(32 * 1024 ~/ 8, null);
}
},
);
final result = await compute(() {
final l = <dynamic>[];
for (int i = 0; i < 10 * 1000 * 1000; ++i) {
l.add(Object());
}
return l;
});
if (result.length != 10 * 1000 * 1000) throw 'failed';
final stats = await statsFuture;
stats.report('IsolateSendExitLatency');
}
Future<T> compute<T>(T Function() fun) {
final rp = ReceivePort();
final sp = rp.sendPort;
Isolate.spawn((_) {
final value = fun();
Isolate.exit(sp, value);
}, null);
return rp.first.then((t) => t as T);
}
@@ -1,140 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:async';
import 'dart:io';
import 'dart:math' as math;
import 'dart:typed_data';
/// Measures event loop responsiveness.
///
/// Schedules new timer events, [tickDuration] in the future, and measures how
/// long it takes for these events to actually arrive.
///
/// Runs [numberOfTicks] times before completing with [EventLoopLatencyStats].
Future<EventLoopLatencyStats> measureEventLoopLatency(
Duration tickDuration,
int numberOfTicks, {
void Function() work,
}) {
final completer = Completer<EventLoopLatencyStats>();
final tickDurationInUs = tickDuration.inMicroseconds;
final buffer = _TickLatencies(numberOfTicks);
final sw = Stopwatch()..start();
int lastTimestamp = 0;
void trigger() {
final int currentTimestamp = sw.elapsedMicroseconds;
// Every tick we missed to schedule we'll add with difference to when we
// would've scheduled it and when we became responsive again.
bool done = false;
while (!done && lastTimestamp < (currentTimestamp - tickDurationInUs)) {
done = !buffer.add(currentTimestamp - lastTimestamp - tickDurationInUs);
lastTimestamp += tickDurationInUs;
}
if (work != null) {
work();
}
if (!done) {
lastTimestamp = currentTimestamp;
Timer(tickDuration, trigger);
} else {
completer.complete(buffer.makeStats());
}
}
Timer(tickDuration, trigger);
return completer.future;
}
/// Result of the event loop latency measurement.
class EventLoopLatencyStats {
/// Minimum latency between scheduling a tick and it's arrival (in ms).
final double minLatency;
/// Average latency between scheduling a tick and it's arrival (in ms).
final double avgLatency;
/// Maximum latency between scheduling a tick and it's arrival (in ms).
final double maxLatency;
/// The 50th percentile (median) (in ms).
final double percentile50th;
/// The 90th percentile (in ms).
final double percentile90th;
/// The 95th percentile (in ms).
final double percentile95th;
/// The 99th percentile (in ms).
final double percentile99th;
EventLoopLatencyStats(
this.minLatency,
this.avgLatency,
this.maxLatency,
this.percentile50th,
this.percentile90th,
this.percentile95th,
this.percentile99th,
);
void report(String name) {
print('$name.Min(RunTimeRaw): $minLatency ms.');
print('$name.Avg(RunTimeRaw): $avgLatency ms.');
print('$name.Percentile50(RunTimeRaw): $percentile50th ms.');
print('$name.Percentile90(RunTimeRaw): $percentile90th ms.');
print('$name.Percentile95(RunTimeRaw): $percentile95th ms.');
print('$name.Percentile99(RunTimeRaw): $percentile99th ms.');
print('$name.Max(RunTimeRaw): $maxLatency ms.');
}
}
/// Accumulates tick latencies and makes statistics for it.
class _TickLatencies {
final Uint64List _timestamps;
int _index = 0;
_TickLatencies(int numberOfTicks) : _timestamps = Uint64List(numberOfTicks);
/// Returns `true` while the buffer has not been filled yet.
bool add(int latencyInUs) {
_timestamps[_index++] = latencyInUs;
return _index < _timestamps.length;
}
EventLoopLatencyStats makeStats() {
if (_index != _timestamps.length) {
throw 'Buffer has not been fully filled yet.';
}
_timestamps.sort();
final length = _timestamps.length;
final double avg = _timestamps.fold(0, (int a, int b) => a + b) / length;
final int min = _timestamps.fold(0x7fffffffffffffff, math.min);
final int max = _timestamps.fold(0, math.max);
final percentile50th = _timestamps[50 * length ~/ 100];
final percentile90th = _timestamps[90 * length ~/ 100];
final percentile95th = _timestamps[95 * length ~/ 100];
final percentile99th = _timestamps[99 * length ~/ 100];
return EventLoopLatencyStats(
min / 1000,
avg / 1000,
max / 1000,
percentile50th / 1000,
percentile90th / 1000,
percentile95th / 1000,
percentile99th / 1000,
);
}
}
@@ -1,183 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:async';
import 'dart:isolate';
import 'dart:math';
import 'package:meta/meta.dart';
import 'package:compiler/src/dart2js.dart' as dart2js_main;
class SpawnLatency {
SpawnLatency(this.name);
Future<ResultMessageLatency> run() async {
final completerResult = Completer();
final receivePort = ReceivePort()..listen(completerResult.complete);
final isolateExitedCompleter = Completer<DateTime>();
final onExitReceivePort =
ReceivePort()..listen((_) {
isolateExitedCompleter.complete(DateTime.now());
});
final beforeSpawn = DateTime.now();
await Isolate.spawn(
isolateCompiler,
StartMessageLatency(receivePort.sendPort, beforeSpawn),
onExit: onExitReceivePort.sendPort,
onError: onExitReceivePort.sendPort,
);
final afterSpawn = DateTime.now();
final ResultMessageLatency result = await completerResult.future;
receivePort.close();
final DateTime isolateExited = await isolateExitedCompleter.future;
result.timeToExitUs = isolateExited.difference(beforeSpawn).inMicroseconds;
result.timeToIsolateSpawnUs =
afterSpawn.difference(beforeSpawn).inMicroseconds;
onExitReceivePort.close();
return result;
}
Future<AggregatedResultMessageLatency> measureFor(int minimumMillis) async {
final minimumMicros = minimumMillis * 1000;
final watch = Stopwatch()..start();
final Metric toAfterIsolateSpawnUs = LatencyMetric('${name}ToAfterSpawn');
final Metric toStartRunningCodeUs = LatencyMetric('${name}ToStartRunning');
final Metric toFinishRunningCodeUs = LatencyMetric(
'${name}ToFinishRunning',
);
final Metric toExitUs = LatencyMetric('${name}ToExit');
while (watch.elapsedMicroseconds < minimumMicros) {
final result = await run();
toAfterIsolateSpawnUs.add(result.timeToIsolateSpawnUs);
toStartRunningCodeUs.add(result.timeToStartRunningCodeUs);
toFinishRunningCodeUs.add(result.timeToFinishRunningCodeUs);
toExitUs.add(result.timeToExitUs);
}
return AggregatedResultMessageLatency(
toAfterIsolateSpawnUs,
toStartRunningCodeUs,
toFinishRunningCodeUs,
toExitUs,
);
}
Future<AggregatedResultMessageLatency> measure() async {
await measureFor(500); // warm-up
return measureFor(4000); // actual measurement
}
Future<void> report() async {
final result = await measure();
print(result);
}
final String name;
RawReceivePort receivePort;
}
class Metric {
Metric({@required this.prefix, @required this.suffix});
void add(int value) {
if (value > max) {
max = value;
}
sum += value;
sumOfSquares += value * value;
count++;
}
double _average() => sum / count;
double _rms() => sqrt(sumOfSquares / count);
@override
String toString() =>
'$prefix): ${_average()}$suffix\n'
'${prefix}Max): $max$suffix\n'
'${prefix}RMS): ${_rms()}$suffix';
final String prefix;
final String suffix;
int max = 0;
double sum = 0;
double sumOfSquares = 0;
int count = 0;
}
class LatencyMetric extends Metric {
LatencyMetric(String name) : super(prefix: '$name(Latency', suffix: ' us.');
}
class StartMessageLatency {
StartMessageLatency(this.sendPort, this.spawned);
final SendPort sendPort;
final DateTime spawned;
}
class ResultMessageLatency {
ResultMessageLatency({
this.timeToStartRunningCodeUs,
this.timeToFinishRunningCodeUs,
this.deltaHeap,
});
final int timeToStartRunningCodeUs;
final int timeToFinishRunningCodeUs;
final int deltaHeap;
int timeToIsolateSpawnUs;
int timeToExitUs;
}
class AggregatedResultMessageLatency {
AggregatedResultMessageLatency(
this.toAfterIsolateSpawnUs,
this.toStartRunningCodeUs,
this.toFinishRunningCodeUs,
this.toExitUs,
);
@override
String toString() => '''$toAfterIsolateSpawnUs
$toStartRunningCodeUs
$toFinishRunningCodeUs
$toExitUs''';
final Metric toAfterIsolateSpawnUs;
final Metric toStartRunningCodeUs;
final Metric toFinishRunningCodeUs;
final Metric toExitUs;
}
Future<void> isolateCompiler(StartMessageLatency start) async {
final timeRunningCodeUs = DateTime.now();
await runZoned(
() => dart2js_main.internalMain(<String>[
'benchmarks/IsolateSpawn/dart/helloworld.dart',
'--libraries-spec=sdk/lib/libraries.json',
]),
zoneSpecification: ZoneSpecification(
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {},
),
);
final timeFinishRunningCodeUs = DateTime.now();
start.sendPort.send(
ResultMessageLatency(
timeToStartRunningCodeUs:
timeRunningCodeUs.difference(start.spawned).inMicroseconds,
timeToFinishRunningCodeUs:
timeFinishRunningCodeUs.difference(start.spawned).inMicroseconds,
),
);
}
Future<void> main() async {
await SpawnLatency('IsolateSpawn.Dart2JS').report();
}
@@ -1,5 +0,0 @@
// @dart=2.9
void main() {
print('Hello, world!');
}
@@ -1,188 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'dart:isolate';
import 'dart:math' as math;
import 'package:compiler/src/dart2js.dart' as dart2js_main;
import 'package:vm_service/vm_service.dart' as vm_service;
import 'package:vm_service/vm_service_io.dart' as vm_service_io;
const String compilerIsolateName = 'isolate-compiler';
class Result {
const Result(
this.rssOnStart,
this.rssOnEnd,
this.heapOnStart,
this.heapOnEnd,
);
final int rssOnStart;
final int rssOnEnd;
final int heapOnStart;
final int heapOnEnd;
}
class StartMessage {
const StartMessage(this.wsUri, this.sendPort);
final String wsUri;
final SendPort sendPort;
}
class SpawnMemory {
SpawnMemory(this.name, this.wsUri);
Future<void> report() async {
int maxProcessRss = 0;
final timer = Timer.periodic(const Duration(microseconds: 100), (_) {
maxProcessRss = math.max(maxProcessRss, ProcessInfo.currentRss);
});
const numberOfBenchmarks = 3;
final beforeRss = ProcessInfo.currentRss;
final beforeHeap = await currentHeapUsage(wsUri);
final iterators = <StreamIterator>[];
final continuations = <SendPort>[];
// Start all isolates & make them wait.
for (int i = 0; i < numberOfBenchmarks; i++) {
final receivePort = ReceivePort();
final startMessage = StartMessage(wsUri, receivePort.sendPort);
await Isolate.spawn(
isolateCompiler,
startMessage,
debugName: compilerIsolateName,
);
final iterator = StreamIterator(receivePort);
if (!await iterator.moveNext()) throw 'failed';
continuations.add(iterator.current as SendPort);
iterators.add(iterator);
}
final readyRss = ProcessInfo.currentRss;
final readyHeap = await currentHeapUsage(wsUri);
// Let all isolates do the dart2js compilation.
for (int i = 0; i < numberOfBenchmarks; i++) {
final iterator = iterators[i];
final continuation = continuations[i];
continuation.send(null);
if (!await iterator.moveNext()) throw 'failed';
if (iterator.current != 'done') throw 'failed';
}
final doneRss = ProcessInfo.currentRss;
final doneHeap = await currentHeapUsage(wsUri);
// Shut down helper isolates
for (int i = 0; i < numberOfBenchmarks; i++) {
final iterator = iterators[i];
final continuation = continuations[i];
continuation.send(null);
if (!await iterator.moveNext()) throw 'failed';
if (iterator.current != 'shutdown') throw 'failed';
await iterator.cancel();
}
timer.cancel();
final readyDiffRss =
math.max(0, readyRss - beforeRss) ~/ numberOfBenchmarks;
final readyDiffHeap =
math.max(0, readyHeap - beforeHeap) ~/ numberOfBenchmarks;
final doneDiffRss = math.max(0, doneRss - beforeRss) ~/ numberOfBenchmarks;
final doneDiffHeap =
math.max(0, doneHeap - beforeHeap) ~/ numberOfBenchmarks;
print('${name}RssOnStart(MemoryUse): $readyDiffRss');
print('${name}RssOnEnd(MemoryUse): $doneDiffRss');
print('${name}HeapOnStart(MemoryUse): $readyDiffHeap');
print('${name}HeapOnEnd(MemoryUse): $doneDiffHeap');
print('${name}PeakProcessRss(MemoryUse): $maxProcessRss');
}
final String name;
final String wsUri;
}
Future<void> isolateCompiler(StartMessage startMessage) async {
final port = ReceivePort();
final iterator = StreamIterator(port);
// Let main isolate know we're ready.
startMessage.sendPort.send(port.sendPort);
await iterator.moveNext();
await runZoned(
() => dart2js_main.internalMain(<String>[
'benchmarks/IsolateSpawnMemory/dart/helloworld.dart',
'--libraries-spec=sdk/lib/libraries.json',
]),
zoneSpecification: ZoneSpecification(
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {},
),
);
// Let main isolate know we're done.
startMessage.sendPort.send('done');
await iterator.moveNext();
// Closes the port.
startMessage.sendPort.send('shutdown');
await iterator.cancel();
}
Future<int> currentHeapUsage(String wsUri) async {
final vmService = await vm_service_io.vmServiceConnectUri(wsUri);
final groupIds = await getGroupIds(vmService);
int sum = 0;
for (final groupId in groupIds) {
final usage = await vmService.getIsolateGroupMemoryUsage(groupId);
sum += usage.heapUsage + usage.externalUsage;
}
vmService.dispose();
return sum;
}
Future<void> main() async {
// Only if we successfully reach the end will we set 0 exit code.
exitCode = 255;
final info = await Service.controlWebServer(enable: true);
final observatoryUri = info.serverUri;
final wsUri = 'ws://${observatoryUri.authority}${observatoryUri.path}ws';
await SpawnMemory('IsolateSpawnMemory.Dart2JSDelta', wsUri).report();
// Only if we successfully reach the end will we set 0 exit code.
exitCode = 0;
}
// Returns the set of isolate groups for which we should count the heap usage.
Future<List<String>> getGroupIds(vm_service.VmService vmService) async {
final groupIds = <String>{};
final vm = await vmService.getVM();
for (final groupRef in vm.isolateGroups) {
final group = await vmService.getIsolateGroup(groupRef.id);
for (final isolateRef in group.isolates) {
final isolateOrSentinel = await vmService.getIsolate(isolateRef.id);
if (isolateOrSentinel is vm_service.Isolate) {
groupIds.add(groupRef.id);
}
}
}
if (groupIds.isEmpty) {
throw 'Could not find main isolate';
}
return groupIds.toList();
}
@@ -1,5 +0,0 @@
// @dart=2.9
void main() {
print('Hello, world!');
}
-11
View File
@@ -1,11 +0,0 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import '../dart/Iterators.dart' as benchmark;
void main(List<String> arguments) {
benchmark.main(arguments);
}
-167
View File
@@ -1,167 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:collection';
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
// Benchmark for polymorphic list copying.
//
// Each benchmark creates a list from an Iterable. There are many slightly
// different ways to do this.
//
// In each benchmark the call site is polymorphic in the input type to simulate
// the behaviour of library methods in the context of a large application. The
// input lists are skewed heavily to the default growable list. This attempts to
// model 'real world' copying of 'ordinary' lists.
//
// The benchmarks are run for small lists (2 elements, names ending in
// `.2`) and 'large' lists (100 elements or `.100`). The benchmarks are
// normalized on the number of elements to make the input sizes comparable.
//
// Most inputs have type `Iterable<num>`, but contain only `int` values. This
// allows is to compare the down-conversion versions of copying where each
// element must be checked.
class Benchmark extends BenchmarkBase {
final int length;
final Function() copy;
final List<Iterable<num>> inputs = [];
Benchmark(String name, this.length, this.copy)
: super('ListCopy.$name.$length');
@override
void setup() {
// Ensure setup() is idempotent.
if (inputs.isNotEmpty) return;
final List<num> base = List.generate(length, (i) => i + 1);
List<Iterable<num>> makeVariants() {
return [
// Weight ordinary lists more.
...List.generate(19, (_) => List<num>.of(base)),
base.toList(growable: false),
List<num>.unmodifiable(base),
UnmodifiableListView(base),
base.reversed,
String.fromCharCodes(List<int>.from(base)).codeUnits,
Uint8List.fromList(List<int>.from(base)),
];
}
const elements = 10000;
int totalLength = 0;
while (totalLength < elements) {
final variants = makeVariants();
inputs.addAll(variants);
totalLength += variants.fold<int>(
0,
(sum, iterable) => sum + iterable.length,
);
}
// Sanity checks.
for (var sample in inputs) {
if (sample.length != length) throw 'Wrong length: $length $sample';
}
if (totalLength != elements) {
throw 'totalLength $totalLength != expected $elements';
}
}
@override
void run() {
for (var sample in inputs) {
input = sample;
// Unroll loop 10 times to reduce loop overhead, which is about 15% for
// the fastest short input benchmarks.
copy();
copy();
copy();
copy();
copy();
copy();
copy();
copy();
copy();
copy();
}
if (output.length != inputs.first.length) throw 'Bad result: $output';
}
}
// All the 'copy' methods use [input] and [output] rather than a parameter and
// return value to avoid any possibility of type check in the call sequence.
Iterable<num> input = const [];
var output;
List<Benchmark> makeBenchmarks(int length) => [
Benchmark('toList', length, () {
output = input.toList();
}),
Benchmark('toList.fixed', length, () {
output = input.toList(growable: false);
}),
Benchmark('List.of', length, () {
output = List<num>.of(input);
}),
Benchmark('List.of.fixed', length, () {
output = List<num>.of(input, growable: false);
}),
Benchmark('List.num.from', length, () {
output = List<num>.from(input);
}),
Benchmark('List.int.from', length, () {
output = List<int>.from(input);
}),
Benchmark('List.num.from.fixed', length, () {
output = List<num>.from(input, growable: false);
}),
Benchmark('List.int.from.fixed', length, () {
output = List<int>.from(input, growable: false);
}),
Benchmark('List.num.unmodifiable', length, () {
output = List<num>.unmodifiable(input);
}),
Benchmark('List.int.unmodifiable', length, () {
output = List<int>.unmodifiable(input);
}),
Benchmark('spread.num', length, () {
output = <num>[...input];
}),
Benchmark('spread.int', length, () {
output = <int>[...input];
}),
Benchmark('spread.int.cast', length, () {
output = <int>[...input.cast<int>()];
}),
Benchmark('spread.int.map', length, () {
output = <int>[...input.map((x) => x as int)];
}),
Benchmark('for.int', length, () {
output = <int>[for (var n in input) n as int];
}),
];
void main() {
final benchmarks = [...makeBenchmarks(2), ...makeBenchmarks(100)];
// Warmup all benchmarks to ensure JIT compilers see full polymorphism.
for (var benchmark in benchmarks) {
benchmark.setup();
}
for (var benchmark in benchmarks) {
benchmark.warmup();
}
for (var benchmark in benchmarks) {
// `report` calls `setup`, but `setup` is idempotent.
benchmark.report();
}
}
-35
View File
@@ -1,35 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
const size = 8 * 1024;
const expected = '6556112372898c69e1de0bf689d8db26';
class MD5Bench extends BenchmarkBase {
List<int> data;
MD5Bench() : super('MD5') {
data = List<int>.filled(size, null);
for (int i = 0; i < data.length; i++) {
data[i] = i % 256;
}
}
@override
void run() {
final hash = md5.convert(data);
if (hex.encode(hash.bytes) != expected) {
throw 'Incorrect HASH computed.';
}
}
}
void main() {
MD5Bench().report();
}
-11
View File
@@ -1,11 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import '../dart/MapCopy.dart' as benchmark;
void main(List<String> arguments) {
benchmark.main(arguments);
}
-131
View File
@@ -1,131 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Benchmark for https://github.com/dart-lang/sdk/issues/45908.
//
// Measures the average time needed for a lookup in Maps.
import 'dart:math';
import 'maps.dart';
abstract class MapLookupBenchmark {
final String name;
const MapLookupBenchmark(this.name);
Map<String, String> get myMap;
// Returns the number of nanoseconds per call.
double measureFor(Duration duration) {
final map = myMap;
// Prevent `sw.elapsedMicroseconds` from dominating with maps with a
// small number of elements.
final int batching = max(1000 ~/ map.length, 1);
int numberOfLookups = 0;
int totalMicroseconds = 0;
final sw = Stopwatch()..start();
final durationInMicroseconds = duration.inMicroseconds;
do {
for (int i = 0; i < batching; i++) {
String? k = '0';
while (k != null) {
k = map[k];
}
numberOfLookups += map.length;
}
totalMicroseconds = sw.elapsedMicroseconds;
} while (totalMicroseconds < durationInMicroseconds);
final int totalNanoseconds = sw.elapsed.inMicroseconds * 1000;
return totalNanoseconds / numberOfLookups;
}
// Runs warmup phase, runs benchmark and reports result.
void report() {
// Warmup for 100 ms.
measureFor(const Duration(milliseconds: 100));
// Run benchmark for 2 seconds.
final double nsPerCall = measureFor(const Duration(seconds: 2));
// Report result.
print('$name(RunTimeRaw): $nsPerCall ns.');
}
}
class Constant1 extends MapLookupBenchmark {
const Constant1() : super('MapLookup.Constant1');
@override
Map<String, String> get myMap => const1;
}
class Final1 extends MapLookupBenchmark {
const Final1() : super('MapLookup.Final1');
@override
Map<String, String> get myMap => final1;
}
class Constant5 extends MapLookupBenchmark {
const Constant5() : super('MapLookup.Constant5');
@override
Map<String, String> get myMap => const5;
}
class Final5 extends MapLookupBenchmark {
const Final5() : super('MapLookup.Final5');
@override
Map<String, String> get myMap => final5;
}
class Constant10 extends MapLookupBenchmark {
const Constant10() : super('MapLookup.Constant10');
@override
Map<String, String> get myMap => const10;
}
class Final10 extends MapLookupBenchmark {
const Final10() : super('MapLookup.Final10');
@override
Map<String, String> get myMap => final10;
}
class Constant100 extends MapLookupBenchmark {
const Constant100() : super('MapLookup.Constant100');
@override
Map<String, String> get myMap => const100;
}
class Final100 extends MapLookupBenchmark {
const Final100() : super('MapLookup.Final100');
@override
Map<String, String> get myMap => final100;
}
void main() {
final benchmarks = [
() => const Constant1(),
() => const Constant5(),
() => const Constant10(),
() => const Constant100(),
() => const Final1(),
() => const Final5(),
() => const Final10(),
() => const Final100(),
];
for (final benchmark in benchmarks) {
benchmark().report();
}
}
-255
View File
@@ -1,255 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
const const1 = <String, String>{'0': '1'};
final final1 = <String, String>{'0': '1'};
const const5 = <String, String>{
'0': '1',
'1': '2',
'2': '3',
'3': '4',
'4': '5',
};
final final5 = <String, String>{
'0': '1',
'1': '2',
'2': '3',
'3': '4',
'4': '5',
};
const const10 = <String, String>{
'0': '1',
'1': '2',
'2': '3',
'3': '4',
'4': '5',
'5': '6',
'6': '7',
'7': '8',
'8': '9',
'9': '10',
};
final final10 = <String, String>{
'0': '1',
'1': '2',
'2': '3',
'3': '4',
'4': '5',
'5': '6',
'6': '7',
'7': '8',
'8': '9',
'9': '10',
};
const const100 = <String, String>{
'0': '1',
'1': '2',
'2': '3',
'3': '4',
'4': '5',
'5': '6',
'6': '7',
'7': '8',
'8': '9',
'9': '10',
'10': '11',
'11': '12',
'12': '13',
'13': '14',
'14': '15',
'15': '16',
'16': '17',
'17': '18',
'18': '19',
'19': '20',
'20': '21',
'21': '22',
'22': '23',
'23': '24',
'24': '25',
'25': '26',
'26': '27',
'27': '28',
'28': '29',
'29': '30',
'30': '31',
'31': '32',
'32': '33',
'33': '34',
'34': '35',
'35': '36',
'36': '37',
'37': '38',
'38': '39',
'39': '40',
'40': '41',
'41': '42',
'42': '43',
'43': '44',
'44': '45',
'45': '46',
'46': '47',
'47': '48',
'48': '49',
'49': '50',
'50': '51',
'51': '52',
'52': '53',
'53': '54',
'54': '55',
'55': '56',
'56': '57',
'57': '58',
'58': '59',
'59': '60',
'60': '61',
'61': '62',
'62': '63',
'63': '64',
'64': '65',
'65': '66',
'66': '67',
'67': '68',
'68': '69',
'69': '70',
'70': '71',
'71': '72',
'72': '73',
'73': '74',
'74': '75',
'75': '76',
'76': '77',
'77': '78',
'78': '79',
'79': '80',
'80': '81',
'81': '82',
'82': '83',
'83': '84',
'84': '85',
'85': '86',
'86': '87',
'87': '88',
'88': '89',
'89': '90',
'90': '91',
'91': '92',
'92': '93',
'93': '94',
'94': '95',
'95': '96',
'96': '97',
'97': '98',
'98': '99',
'99': '100',
};
final final100 = <String, String>{
'0': '1',
'1': '2',
'2': '3',
'3': '4',
'4': '5',
'5': '6',
'6': '7',
'7': '8',
'8': '9',
'9': '10',
'10': '11',
'11': '12',
'12': '13',
'13': '14',
'14': '15',
'15': '16',
'16': '17',
'17': '18',
'18': '19',
'19': '20',
'20': '21',
'21': '22',
'22': '23',
'23': '24',
'24': '25',
'25': '26',
'26': '27',
'27': '28',
'28': '29',
'29': '30',
'30': '31',
'31': '32',
'32': '33',
'33': '34',
'34': '35',
'35': '36',
'36': '37',
'37': '38',
'38': '39',
'39': '40',
'40': '41',
'41': '42',
'42': '43',
'43': '44',
'44': '45',
'45': '46',
'46': '47',
'47': '48',
'48': '49',
'49': '50',
'50': '51',
'51': '52',
'52': '53',
'53': '54',
'54': '55',
'55': '56',
'56': '57',
'57': '58',
'58': '59',
'59': '60',
'60': '61',
'61': '62',
'62': '63',
'63': '64',
'64': '65',
'65': '66',
'66': '67',
'67': '68',
'68': '69',
'69': '70',
'70': '71',
'71': '72',
'72': '73',
'73': '74',
'74': '75',
'75': '76',
'76': '77',
'77': '78',
'78': '79',
'79': '80',
'80': '81',
'81': '82',
'82': '83',
'83': '84',
'84': '85',
'85': '86',
'86': '87',
'87': '88',
'88': '89',
'89': '90',
'90': '91',
'91': '92',
'92': '93',
'93': '94',
'94': '95',
'95': '96',
'96': '97',
'97': '98',
'98': '99',
'99': '100',
};
-327
View File
@@ -1,327 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// These micro benchmarks track the speed of native calls.
// @dart=2.9
import 'dart:ffi';
import 'dart:io';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'dlopen_helper.dart';
// Number of benchmark iterations per function.
const N = 1000;
// The native library that holds all the native functions being called.
final nativeFunctionsLib = dlopenPlatformSpecific(
'native_functions',
path: Platform.script.resolve('../native/out/').path,
);
final getRootLibraryUrl = nativeFunctionsLib
.lookupFunction<Handle Function(), Object Function()>('GetRootLibraryUrl');
final setNativeResolverForTest = nativeFunctionsLib
.lookupFunction<Void Function(Handle), void Function(Object)>(
'SetNativeResolverForTest',
);
//
// Benchmark fixtures.
//
abstract class NativeCallBenchmarkBase extends BenchmarkBase {
NativeCallBenchmarkBase(String name) : super(name);
void expectEquals(actual, expected) {
if (actual != expected) {
throw Exception('$name: Unexpected result: $actual, expected $expected');
}
}
void expectApprox(actual, expected) {
if (0.999 * expected > actual || actual > 1.001 * expected) {
throw Exception('$name: Unexpected result: $actual, expected $expected');
}
}
void expectIdentical(actual, expected) {
if (!identical(actual, expected)) {
throw Exception('$name: Unexpected result: $actual, expected $expected');
}
}
}
class Uint8x01 extends NativeCallBenchmarkBase {
Uint8x01() : super('NativeCall.Uint8x01');
@pragma('vm:external-name', 'Function1Uint8')
external static int f(int a);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(17);
}
expectEquals(x, N * 17 + N * 42);
}
}
class Int64x20 extends NativeCallBenchmarkBase {
Int64x20() : super('NativeCall.Int64x20');
@pragma('vm:external-name', 'Function20Int64')
external static int f(
int a,
int b,
int c,
int d,
int e,
int f,
int g,
int h,
int i,
int j,
int k,
int l,
int m,
int n,
int o,
int p,
int q,
int r,
int s,
int t,
);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i);
}
expectEquals(x, N * (N - 1) * 20 / 2);
}
}
class Doublex01 extends NativeCallBenchmarkBase {
Doublex01() : super('NativeCall.Doublex01');
@pragma('vm:external-name', 'Function1Double')
external static double f(double a);
@override
void run() {
double x = 0.0;
for (int i = 0; i < N; i++) {
x += f(17.0);
}
final double expected = N * (17.0 + 42.0);
expectApprox(x, expected);
}
}
class Doublex20 extends NativeCallBenchmarkBase {
Doublex20() : super('NativeCall.Doublex20');
@pragma('vm:external-name', 'Function20Double')
external static double f(
double a,
double b,
double c,
double d,
double e,
double f,
double g,
double h,
double i,
double j,
double k,
double l,
double m,
double n,
double o,
double p,
double q,
double r,
double s,
double t,
);
@override
void run() {
double x = 0;
for (int i = 0; i < N; i++) {
x += f(
1.0,
2.0,
3.0,
4.0,
5.0,
6.0,
7.0,
8.0,
9.0,
10.0,
11.0,
12.0,
13.0,
14.0,
15.0,
16.0,
17.0,
18.0,
19.0,
20.0,
);
}
final double expected =
N *
(1.0 +
2.0 +
3.0 +
4.0 +
5.0 +
6.0 +
7.0 +
8.0 +
9.0 +
10.0 +
11.0 +
12.0 +
13.0 +
14.0 +
15.0 +
16.0 +
17.0 +
18.0 +
19.0 +
20.0);
expectApprox(x, expected);
}
}
class MyClass {
int a;
MyClass(this.a);
}
class Handlex01 extends NativeCallBenchmarkBase {
Handlex01() : super('NativeCall.Handlex01');
@pragma('vm:external-name', 'Function1Handle')
external static Object f(Object a);
@override
void run() {
final p1 = MyClass(123);
Object x = p1;
for (int i = 0; i < N; i++) {
x = f(x);
}
expectIdentical(x, p1);
}
}
class Handlex20 extends NativeCallBenchmarkBase {
Handlex20() : super('NativeCall.Handlex20');
@pragma('vm:external-name', 'Function20Handle')
external static Object f(
Object a,
Object b,
Object c,
Object d,
Object e,
Object f,
Object g,
Object h,
Object i,
Object j,
Object k,
Object l,
Object m,
Object n,
Object o,
Object p,
Object q,
Object r,
Object s,
Object t,
);
@override
void run() {
final p1 = MyClass(123);
final p2 = MyClass(2);
final p3 = MyClass(3);
final p4 = MyClass(4);
final p5 = MyClass(5);
final p6 = MyClass(6);
final p7 = MyClass(7);
final p8 = MyClass(8);
final p9 = MyClass(9);
final p10 = MyClass(10);
final p11 = MyClass(11);
final p12 = MyClass(12);
final p13 = MyClass(13);
final p14 = MyClass(14);
final p15 = MyClass(15);
final p16 = MyClass(16);
final p17 = MyClass(17);
final p18 = MyClass(18);
final p19 = MyClass(19);
final p20 = MyClass(20);
Object x = p1;
for (int i = 0; i < N; i++) {
x = f(
x,
p2,
p3,
p4,
p5,
p6,
p7,
p8,
p9,
p10,
p11,
p12,
p13,
p14,
p15,
p16,
p17,
p18,
p19,
p20,
);
}
expectIdentical(x, p1);
}
}
//
// Main driver.
//
void main() {
setNativeResolverForTest(getRootLibraryUrl());
final benchmarks = [
() => Uint8x01(),
() => Int64x20(),
() => Doublex01(),
() => Doublex20(),
() => Handlex01(),
() => Handlex20(),
];
for (final benchmark in benchmarks) {
benchmark().report();
}
}
@@ -1,63 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:ffi';
import 'dart:io';
const arm = 'arm';
const arm64 = 'arm64';
const ia32 = 'ia32';
const x64 = 'x64';
// https://stackoverflow.com/questions/45125516/possible-values-for-uname-m
final _unames = {
'arm': arm,
'aarch64_be': arm64,
'aarch64': arm64,
'armv8b': arm64,
'armv8l': arm64,
'i386': ia32,
'i686': ia32,
'x86_64': x64,
};
String _checkRunningMode(String architecture) {
// Check if we're running in 32bit mode.
final int pointerSize = sizeOf<IntPtr>();
if (pointerSize == 4 && architecture == x64) return ia32;
if (pointerSize == 4 && architecture == arm64) return arm;
return architecture;
}
String _architecture() {
final String uname = Process.runSync('uname', ['-m']).stdout.trim();
final String architecture = _unames[uname];
if (architecture == null) {
throw Exception('Unrecognized architecture: "$uname"');
}
// Check if we're running in 32bit mode.
return _checkRunningMode(architecture);
}
String _platformPath(String name, {String path = ''}) {
if (Platform.isMacOS || Platform.isIOS) {
return '${path}mac/${_architecture()}/lib$name.dylib';
}
if (Platform.isWindows) {
return '${path}win/${_checkRunningMode(x64)}/$name.dll';
}
// Unknown platforms default to Unix implementation.
return '${path}linux/${_architecture()}/lib$name.so';
}
DynamicLibrary dlopenPlatformSpecific(String name, {String path}) {
final String fullPath = _platformPath(name, path: path);
return DynamicLibrary.open(fullPath);
}
@@ -1,11 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import '../dart/ObjectHash.dart' as benchmark;
void main() {
benchmark.main();
}
-81
View File
@@ -1,81 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
// @dart=2.10
//
// A benchmark that contains several other benchmarks.
//
// With no arguments, run all benchmarks once.
// With arguments, run only the specified benchmarks in command-line order.
//
// -N: run benchmarks N times, defaults to once.
// ignore_for_file: library_prefixes
import '../../BigIntParsePrint/dart2/BigIntParsePrint.dart'
as lib_BigIntParsePrint;
import '../../ListCopy/dart2/ListCopy.dart' as lib_ListCopy;
import '../../MapCopy/dart2/MapCopy.dart' as lib_MapCopy;
import '../../MD5/dart2/md5.dart' as lib_MD5;
import '../../RuntimeType/dart2/RuntimeType.dart' as lib_RuntimeType;
import '../../SHA1/dart2/sha1.dart' as lib_SHA1;
import '../../SHA256/dart2/sha256.dart' as lib_SHA256;
import '../../SkeletalAnimation/dart2/SkeletalAnimation.dart'
as lib_SkeletalAnimation;
import '../../SkeletalAnimationSIMD/dart2/SkeletalAnimationSIMD.dart'
as lib_SkeletalAnimationSIMD;
import '../../TypedDataDuplicate/dart2/TypedDataDuplicate.dart'
as lib_TypedDataDuplicate;
import '../../Utf8Decode/dart2/Utf8Decode.dart' as lib_Utf8Decode;
import '../../Utf8Encode/dart2/Utf8Encode.dart' as lib_Utf8Encode;
final Map<String, Function()> benchmarks = {
'BigIntParsePrint': lib_BigIntParsePrint.main,
'ListCopy': lib_ListCopy.main,
'MapCopy': () => lib_MapCopy.main([]),
'MD5': lib_MD5.main,
'RuntimeType': lib_RuntimeType.main,
'SHA1': lib_SHA1.main,
'SHA256': lib_SHA256.main,
'SkeletalAnimation': lib_SkeletalAnimation.main,
'SkeletalAnimationSIMD': lib_SkeletalAnimationSIMD.main,
'TypedDataDuplicate': lib_TypedDataDuplicate.main,
'Utf8Decode': () => lib_Utf8Decode.main([]),
'Utf8Encode': () => lib_Utf8Encode.main([]),
};
void main(List<String> originalArguments) {
final List<String> args = List.of(originalArguments);
int repeats = 1;
for (final arg in args.toList()) {
final int count = int.tryParse(arg);
if (count != null && count < 0) {
repeats = 0 - count;
args.remove(arg);
}
}
List<Function()> mains = [];
for (final name in args.toList()) {
final function = benchmarks[name];
if (function == null) {
print("Unknown benchmark: '$name'");
} else {
mains.add(function);
args.remove(name);
}
}
if (args.isNotEmpty) return; // We will have printed an error.
if (mains.isEmpty) mains = benchmarks.values.toList();
for (var i = 0; i < repeats; i++) {
for (final function in mains) {
function();
}
}
}
@@ -1,108 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
// @dart=2.10
//
// A benchmark that contains several other benchmarks.
//
// With no arguments, run all benchmarks once.
// With arguments, run only the specified benchmarks in command-line order.
//
// -N: run benchmarks N times, defaults to once.
// ignore_for_file: library_prefixes
import '../../BigIntParsePrint/dart2/BigIntParsePrint.dart'
deferred as lib_BigIntParsePrint;
import '../../ListCopy/dart2/ListCopy.dart' deferred as lib_ListCopy;
import '../../MapCopy/dart/MapCopy.dart' deferred as lib_MapCopy;
import '../../MD5/dart2/md5.dart' deferred as lib_MD5;
import '../../RuntimeType/dart2/RuntimeType.dart' deferred as lib_RuntimeType;
import '../../SHA1/dart2/sha1.dart' deferred as lib_SHA1;
import '../../SHA256/dart2/sha256.dart' deferred as lib_SHA256;
import '../../SkeletalAnimation/dart2/SkeletalAnimation.dart'
deferred as lib_SkeletalAnimation;
import '../../SkeletalAnimationSIMD/dart2/SkeletalAnimationSIMD.dart'
deferred as lib_SkeletalAnimationSIMD;
import '../../TypedDataDuplicate/dart2/TypedDataDuplicate.dart'
deferred as lib_TypedDataDuplicate;
import '../../Utf8Decode/dart2/Utf8Decode.dart' deferred as lib_Utf8Decode;
import '../../Utf8Encode/dart2/Utf8Encode.dart' deferred as lib_Utf8Encode;
class Lib {
final Future Function() load;
final void Function() main;
Lib(this.load, this.main);
}
final Map<String, Lib> benchmarks = {
'BigIntParsePrint': Lib(
lib_BigIntParsePrint.loadLibrary,
() => lib_BigIntParsePrint.main(),
),
'ListCopy': Lib(lib_ListCopy.loadLibrary, () => lib_ListCopy.main()),
'MapCopy': Lib(lib_MapCopy.loadLibrary, () => lib_MapCopy.main([])),
'MD5': Lib(lib_MD5.loadLibrary, () => lib_MD5.main()),
'RuntimeType': Lib(lib_RuntimeType.loadLibrary, () => lib_RuntimeType.main()),
'SHA1': Lib(lib_SHA1.loadLibrary, () => lib_SHA1.main()),
'SHA256': Lib(lib_SHA256.loadLibrary, () => lib_SHA256.main()),
'SkeletalAnimation': Lib(
lib_SkeletalAnimation.loadLibrary,
() => lib_SkeletalAnimation.main(),
),
'SkeletalAnimationSIMD': Lib(
lib_SkeletalAnimationSIMD.loadLibrary,
() => lib_SkeletalAnimationSIMD.main(),
),
'TypedDataDuplicate': Lib(
lib_TypedDataDuplicate.loadLibrary,
() => lib_TypedDataDuplicate.main(),
),
'Utf8Decode': Lib(lib_Utf8Decode.loadLibrary, () => lib_Utf8Decode.main([])),
'Utf8Encode': Lib(lib_Utf8Encode.loadLibrary, () => lib_Utf8Encode.main([])),
};
void main(List<String> originalArguments) async {
final List<String> args = List.of(originalArguments);
int repeats = 1;
for (final arg in args.toList()) {
final int count = int.tryParse(arg);
if (count != null && count < 0) {
repeats = 0 - count;
args.remove(arg);
}
}
final preload = args.remove('--preload');
List<Lib> libs = [];
for (final name in args.toList()) {
final lib = benchmarks[name];
if (lib == null) {
print("Unknown benchmark: '$name'");
} else {
libs.add(lib);
args.remove(name);
}
}
if (args.isNotEmpty) return; // We will have printed an error.
if (libs.isEmpty) libs = benchmarks.values.toList();
if (preload) {
for (final lib in libs) {
await lib.load();
}
}
for (var i = 0; i < repeats; i++) {
for (final lib in libs) {
if (!preload) await lib.load();
lib.main();
}
}
}
-453
View File
@@ -1,453 +0,0 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Ported by the Dart team to Dart.
// This is a Dart implementation of the Richards benchmark from:
//
// http://www.cl.cam.ac.uk/~mr10/Bench.html
//
// The benchmark was originally implemented in BCPL by
// Martin Richards.
// @dart=2.9
import 'package:benchmark_harness/benchmark_harness.dart';
void main() {
const Richards().report();
}
/// Richards imulates the task dispatcher of an operating system.
class Richards extends BenchmarkBase {
const Richards() : super('Richards');
@override
void run() {
final Scheduler scheduler = Scheduler();
scheduler.addIdleTask(ID_IDLE, 0, null, COUNT);
Packet queue = Packet(null, ID_WORKER, KIND_WORK);
queue = Packet(queue, ID_WORKER, KIND_WORK);
scheduler.addWorkerTask(ID_WORKER, 1000, queue);
queue = Packet(null, ID_DEVICE_A, KIND_DEVICE);
queue = Packet(queue, ID_DEVICE_A, KIND_DEVICE);
queue = Packet(queue, ID_DEVICE_A, KIND_DEVICE);
scheduler.addHandlerTask(ID_HANDLER_A, 2000, queue);
queue = Packet(null, ID_DEVICE_B, KIND_DEVICE);
queue = Packet(queue, ID_DEVICE_B, KIND_DEVICE);
queue = Packet(queue, ID_DEVICE_B, KIND_DEVICE);
scheduler.addHandlerTask(ID_HANDLER_B, 3000, queue);
scheduler.addDeviceTask(ID_DEVICE_A, 4000, null);
scheduler.addDeviceTask(ID_DEVICE_B, 5000, null);
scheduler.schedule();
if (scheduler.queueCount != EXPECTED_QUEUE_COUNT ||
scheduler.holdCount != EXPECTED_HOLD_COUNT) {
print(
'Error during execution: queueCount = ${scheduler.queueCount}'
', holdCount = ${scheduler.holdCount}.',
);
}
if (EXPECTED_QUEUE_COUNT != scheduler.queueCount) {
throw 'bad scheduler queue-count';
}
if (EXPECTED_HOLD_COUNT != scheduler.holdCount) {
throw 'bad scheduler hold-count';
}
}
static const int DATA_SIZE = 4;
static const int COUNT = 1000;
/// These two constants specify how many times a packet is queued and
/// how many times a task is put on hold in a correct run of richards.
/// They don't have any meaning a such but are characteristic of a
/// correct run so if the actual queue or hold count is different from
/// the expected there must be a bug in the implementation.
static const int EXPECTED_QUEUE_COUNT = 2322;
static const int EXPECTED_HOLD_COUNT = 928;
static const int ID_IDLE = 0;
static const int ID_WORKER = 1;
static const int ID_HANDLER_A = 2;
static const int ID_HANDLER_B = 3;
static const int ID_DEVICE_A = 4;
static const int ID_DEVICE_B = 5;
static const int NUMBER_OF_IDS = 6;
static const int KIND_DEVICE = 0;
static const int KIND_WORK = 1;
}
/// A scheduler can be used to schedule a set of tasks based on their relative
/// priorities. Scheduling is done by maintaining a list of task control blocks
/// which holds tasks and the data queue they are processing.
class Scheduler {
int queueCount = 0;
int holdCount = 0;
TaskControlBlock currentTcb;
int currentId;
TaskControlBlock list;
List<TaskControlBlock> blocks = List<TaskControlBlock>.filled(
Richards.NUMBER_OF_IDS,
null,
);
/// Add an idle task to this scheduler.
void addIdleTask(int id, int priority, Packet queue, int count) {
addRunningTask(id, priority, queue, IdleTask(this, 1, count));
}
/// Add a work task to this scheduler.
void addWorkerTask(int id, int priority, Packet queue) {
addTask(id, priority, queue, WorkerTask(this, Richards.ID_HANDLER_A, 0));
}
/// Add a handler task to this scheduler.
void addHandlerTask(int id, int priority, Packet queue) {
addTask(id, priority, queue, HandlerTask(this));
}
/// Add a handler task to this scheduler.
void addDeviceTask(int id, int priority, Packet queue) {
addTask(id, priority, queue, DeviceTask(this));
}
/// Add the specified task and mark it as running.
void addRunningTask(int id, int priority, Packet queue, Task task) {
addTask(id, priority, queue, task);
currentTcb.setRunning();
}
/// Add the specified task to this scheduler.
void addTask(int id, int priority, Packet queue, Task task) {
currentTcb = TaskControlBlock(list, id, priority, queue, task);
list = currentTcb;
blocks[id] = currentTcb;
}
/// Execute the tasks managed by this scheduler.
void schedule() {
currentTcb = list;
while (currentTcb != null) {
if (currentTcb.isHeldOrSuspended()) {
currentTcb = currentTcb.link;
} else {
currentId = currentTcb.id;
currentTcb = currentTcb.run();
}
}
}
/// Release a task that is currently blocked and return the next block to run.
TaskControlBlock release(int id) {
final TaskControlBlock tcb = blocks[id];
if (tcb == null) return tcb;
tcb.markAsNotHeld();
if (tcb.priority > currentTcb.priority) return tcb;
return currentTcb;
}
/// Block the currently executing task and return the next task control block
/// to run. The blocked task will not be made runnable until it is explicitly
/// released, even if new work is added to it.
TaskControlBlock holdCurrent() {
holdCount++;
currentTcb.markAsHeld();
return currentTcb.link;
}
/// Suspend the currently executing task and return the next task
/// control block to run.
/// If new work is added to the suspended task it will be made runnable.
TaskControlBlock suspendCurrent() {
currentTcb.markAsSuspended();
return currentTcb;
}
/// Add the specified packet to the end of the worklist used by the task
/// associated with the packet and make the task runnable if it is currently
/// suspended.
TaskControlBlock queue(Packet packet) {
final TaskControlBlock t = blocks[packet.id];
if (t == null) return t;
queueCount++;
packet.link = null;
packet.id = currentId;
return t.checkPriorityAdd(currentTcb, packet);
}
}
/// A task control block manages a task and the queue of work packages
/// associated with it.
class TaskControlBlock {
TaskControlBlock link;
int id; // The id of this block.
int priority; // The priority of this block.
Packet queue; // The queue of packages to be processed by the task.
Task task;
int state;
TaskControlBlock(this.link, this.id, this.priority, this.queue, this.task) {
state = queue == null ? STATE_SUSPENDED : STATE_SUSPENDED_RUNNABLE;
}
/// The task is running and is currently scheduled.
static const int STATE_RUNNING = 0;
/// The task has packets left to process.
static const int STATE_RUNNABLE = 1;
/// The task is not currently running. The task is not blocked as such and may
/// be started by the scheduler.
static const int STATE_SUSPENDED = 2;
/// The task is blocked and cannot be run until it is explicitly released.
static const int STATE_HELD = 4;
static const int STATE_SUSPENDED_RUNNABLE = STATE_SUSPENDED | STATE_RUNNABLE;
static const int STATE_NOT_HELD = ~STATE_HELD;
void setRunning() {
state = STATE_RUNNING;
}
void markAsNotHeld() {
state = state & STATE_NOT_HELD;
}
void markAsHeld() {
state = state | STATE_HELD;
}
bool isHeldOrSuspended() {
return (state & STATE_HELD) != 0 || (state == STATE_SUSPENDED);
}
void markAsSuspended() {
state = state | STATE_SUSPENDED;
}
void markAsRunnable() {
state = state | STATE_RUNNABLE;
}
/// Runs this task, if it is ready to be run, and returns the next
/// task to run.
TaskControlBlock run() {
Packet packet;
if (state == STATE_SUSPENDED_RUNNABLE) {
packet = queue;
queue = packet.link;
state = queue == null ? STATE_RUNNING : STATE_RUNNABLE;
} else {
packet = null;
}
return task.run(packet);
}
/// Adds a packet to the worklist of this block's task, marks this as
/// runnable if necessary, and returns the next runnable object to run
/// (the one with the highest priority).
TaskControlBlock checkPriorityAdd(TaskControlBlock task, Packet packet) {
if (queue == null) {
queue = packet;
markAsRunnable();
if (priority > task.priority) return this;
} else {
queue = packet.addTo(queue);
}
return task;
}
@override
String toString() => 'tcb { $task@$state }';
}
/// Abstract task that manipulates work packets.
abstract class Task {
Scheduler scheduler; // The scheduler that manages this task.
Task(this.scheduler);
TaskControlBlock run(Packet packet);
}
/// An idle task doesn't do any work itself but cycles control between the two
/// device tasks.
class IdleTask extends Task {
int v1; // A seed value that controls how the device tasks are scheduled.
int count; // The number of times this task should be scheduled.
IdleTask(Scheduler scheduler, this.v1, this.count) : super(scheduler);
@override
TaskControlBlock run(Packet packet) {
count--;
if (count == 0) return scheduler.holdCurrent();
if ((v1 & 1) == 0) {
v1 = v1 >> 1;
return scheduler.release(Richards.ID_DEVICE_A);
}
v1 = (v1 >> 1) ^ 0xD008;
return scheduler.release(Richards.ID_DEVICE_B);
}
@override
String toString() => 'IdleTask';
}
/// A task that suspends itself after each time it has been run to simulate
/// waiting for data from an external device.
class DeviceTask extends Task {
Packet v1;
DeviceTask(Scheduler scheduler) : super(scheduler);
@override
TaskControlBlock run(Packet packet) {
if (packet == null) {
if (v1 == null) return scheduler.suspendCurrent();
final Packet v = v1;
v1 = null;
return scheduler.queue(v);
}
v1 = packet;
return scheduler.holdCurrent();
}
@override
String toString() => 'DeviceTask';
}
/// A task that manipulates work packets.
class WorkerTask extends Task {
int v1; // A seed used to specify how work packets are manipulated.
int v2; // Another seed used to specify how work packets are manipulated.
WorkerTask(Scheduler scheduler, this.v1, this.v2) : super(scheduler);
@override
TaskControlBlock run(Packet packet) {
if (packet == null) {
return scheduler.suspendCurrent();
}
if (v1 == Richards.ID_HANDLER_A) {
v1 = Richards.ID_HANDLER_B;
} else {
v1 = Richards.ID_HANDLER_A;
}
packet.id = v1;
packet.a1 = 0;
for (int i = 0; i < Richards.DATA_SIZE; i++) {
v2++;
if (v2 > 26) v2 = 1;
packet.a2[i] = v2;
}
return scheduler.queue(packet);
}
@override
String toString() => 'WorkerTask';
}
/// A task that manipulates work packets and then suspends itself.
class HandlerTask extends Task {
Packet v1;
Packet v2;
HandlerTask(Scheduler scheduler) : super(scheduler);
@override
TaskControlBlock run(Packet packet) {
if (packet != null) {
if (packet.kind == Richards.KIND_WORK) {
v1 = packet.addTo(v1);
} else {
v2 = packet.addTo(v2);
}
}
if (v1 != null) {
final int count = v1.a1;
Packet v;
if (count < Richards.DATA_SIZE) {
if (v2 != null) {
v = v2;
v2 = v2.link;
v.a1 = v1.a2[count];
v1.a1 = count + 1;
return scheduler.queue(v);
}
} else {
v = v1;
v1 = v1.link;
return scheduler.queue(v);
}
}
return scheduler.suspendCurrent();
}
@override
String toString() => 'HandlerTask';
}
/// A simple package of data that is manipulated by the tasks. The exact layout
/// of the payload data carried by a packet is not important, and neither is
/// the nature of the work performed on packets by the tasks. Besides carrying
/// data, packets form linked lists and are hence used both as data and
/// worklists.
class Packet {
Packet link; // The tail of the linked list of packets.
int id; // An ID for this packet.
int kind; // The type of this packet.
int a1 = 0;
List<int> a2 = List.filled(Richards.DATA_SIZE, null);
Packet(this.link, this.id, this.kind);
/// Add this packet to the end of a worklist, and return the worklist.
Packet addTo(Packet queue) {
link = null;
if (queue == null) return this;
Packet peek, next = queue;
while ((peek = next.link) != null) {
next = peek;
}
next.link = this;
return queue;
}
@override
String toString() => 'Packet';
}
@@ -1,175 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
// Benchmark for runtimeType patterns as used in Flutter.
// ignore_for_file: prefer_const_constructors
// ignore_for_file: avoid_function_literals_in_foreach_calls
// @dart=2.9
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
abstract class Key {
const factory Key(String value) = ValueKey<String>;
const Key.empty();
}
abstract class LocalKey extends Key {
const LocalKey() : super.empty();
}
class ValueKey<T> extends LocalKey {
const ValueKey(this.value);
final T value;
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType) return false;
return other is ValueKey<T> && other.value == value;
}
@override
int get hashCode => value.hashCode;
}
abstract class Widget {
const Widget({this.key});
final Key key;
@pragma('dart2js:noInline')
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType &&
oldWidget.key == newWidget.key;
}
}
class AWidget extends Widget {
const AWidget({Key key}) : super(key: key);
}
class BWidget extends Widget {
const BWidget({Key key}) : super(key: key);
}
class CWidget extends Widget {
const CWidget({Key key}) : super(key: key);
}
class DWidget extends Widget {
const DWidget({Key key}) : super(key: key);
}
class EWidget extends Widget {
const EWidget({Key key}) : super(key: key);
}
class FWidget extends Widget {
const FWidget({Key key}) : super(key: key);
}
class WWidget<W extends Widget> extends Widget {
final W /*?*/ ref;
const WWidget({this.ref, Key key}) : super(key: key);
}
class WidgetCanUpdateBenchmark extends BenchmarkBase {
WidgetCanUpdateBenchmark() : super('RuntimeType.Widget.canUpdate.byType');
// All widgets have different types.
static List<Widget> _widgets() => [
AWidget(),
BWidget(),
CWidget(),
DWidget(),
EWidget(),
FWidget(),
WWidget<AWidget>(),
WWidget<BWidget>(ref: const BWidget()),
WWidget<CWidget>(ref: CWidget()),
const WWidget<DWidget>(ref: DWidget()),
];
// Bulk up list to reduce loop overheads.
final List<Widget> widgets = _widgets() + _widgets() + _widgets();
@override
void exercise() => run();
@override
void run() {
for (var w1 in widgets) {
for (var w2 in widgets) {
if (Widget.canUpdate(w1, w2) != Widget.canUpdate(w2, w1)) {
throw 'Hmm $w1 $w2';
}
}
}
}
// Normalize by number of calls to [Widgets.canUpdate].
@override
double measure() => super.measure() / (widgets.length * widgets.length * 2);
}
class ValueKeyEqualBenchmark extends BenchmarkBase {
ValueKeyEqualBenchmark() : super('RuntimeType.Widget.canUpdate.byKey');
// All widgets the same class but distinguished on keys.
static List<Widget> _widgets() => [
AWidget(),
AWidget(key: ValueKey(1)),
AWidget(key: ValueKey(1)),
AWidget(key: ValueKey(2)),
AWidget(key: ValueKey(2)),
AWidget(key: ValueKey(3)),
AWidget(key: ValueKey('one')),
AWidget(key: ValueKey('two')),
AWidget(key: ValueKey('three')),
AWidget(key: ValueKey(Duration(seconds: 5))),
];
// Bulk up list to reduce loop overheads.
final List<Widget> widgets = _widgets() + _widgets() + _widgets();
@override
void exercise() => run();
@override
void run() {
for (var w1 in widgets) {
for (var w2 in widgets) {
if (Widget.canUpdate(w1, w2) != Widget.canUpdate(w2, w1)) {
throw 'Hmm $w1 $w2';
}
}
}
}
// Normalize by number of calls to [Widgets.canUpdate].
@override
double measure() => super.measure() / (widgets.length * widgets.length * 2);
}
void pollute() {
// Various bits of code to make environment less unrealistic.
void check(dynamic a, dynamic b) {
if (a.runtimeType != b.runtimeType) throw 'mismatch $a $b';
}
check(Uint8List(1), Uint8List(2)); // dart2js needs native interceptors.
check(Int16List(1), Int16List(2));
check([], []);
check(<bool>{}, <bool>{});
}
void main() {
pollute();
final benchmarks = [WidgetCanUpdateBenchmark(), ValueKeyEqualBenchmark()];
// Warm up all benchmarks before running any.
benchmarks.forEach((bm) => bm.run());
benchmarks.forEach((bm) => bm.report());
}
@@ -1,88 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
// Reports the sizes of binary artifacts shipped with the SDK.
import 'dart:io';
const executables = <String>['dart', 'dartaotruntime'];
const libs = <String>[
'vm_platform_strong.dill',
'vm_platform_strong_product.dill',
];
const snapshots = <String>[
'analysis_server',
'dart2js',
'dart2wasm',
'dartdev',
'dartdevc',
'dds_aot',
'frontend_server',
'gen_kernel',
'kernel-service',
'kernel_worker',
];
const resources = <String>['devtools'];
void reportFileSize(String path, String name) {
try {
final size = File(path).lengthSync();
print('SDKArtifactSizes.$name(CodeSize): $size');
} on FileSystemException {
// Report dummy data for artifacts that don't exist for specific platforms.
print('SDKArtifactSizes.$name(CodeSize): 0');
}
}
void reportDirectorySize(String path, String name) async {
final dir = Directory(path);
try {
final size = dir
.listSync(recursive: true, followLinks: false)
.whereType<File>()
.map((file) => file.lengthSync())
.fold<int>(0, (a, b) => a + b);
print('SDKArtifactSizes.$name(CodeSize): $size');
} on FileSystemException {
// Report dummy data on errors.
print('SDKArtifactSizes.$name(CodeSize): 0');
}
}
void main() {
final topDirIndex = Platform.resolvedExecutable.lastIndexOf(
Platform.pathSeparator,
);
final rootDir = Platform.resolvedExecutable.substring(0, topDirIndex);
for (final executable in executables) {
final executablePath = '$rootDir/dart-sdk/bin/$executable';
reportFileSize(executablePath, executable);
}
for (final lib in libs) {
final libPath = '$rootDir/dart-sdk/lib/_internal/$lib';
reportFileSize(libPath, lib);
}
for (final snapshot in snapshots) {
final snapshotPath =
'$rootDir/dart-sdk/bin/snapshots/$snapshot.dart.snapshot';
reportFileSize(snapshotPath, snapshot);
}
for (final resource in resources) {
final resourcePath = '$rootDir/dart-sdk/bin/resources/$resource';
reportDirectorySize(resourcePath, resource);
}
// Measure the sdk size.
reportDirectorySize('$rootDir/dart-sdk', 'sdk');
}
-35
View File
@@ -1,35 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
const size = 8 * 1024;
const expected = 'ecca46e1a1d0a6012713b09a870d84f695b6d9b0';
class SHA1Bench extends BenchmarkBase {
List<int> data;
SHA1Bench() : super('SHA1') {
data = List<int>.filled(size, null);
for (int i = 0; i < data.length; i++) {
data[i] = i % 256;
}
}
@override
void run() {
final hash = sha1.convert(data);
if (hex.encode(hash.bytes) != expected) {
throw 'Incorrect HASH computed.';
}
}
}
void main() {
SHA1Bench().report();
}
-36
View File
@@ -1,36 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
const size = 8 * 1024;
const expected =
'dc404a613fedaeb54034514bc6505f56b933caa5250299ba7d094377a51caa46';
class SHA256Bench extends BenchmarkBase {
List<int> data;
SHA256Bench() : super('SHA256') {
data = List<int>.filled(size, null);
for (int i = 0; i < data.length; i++) {
data[i] = i % 256;
}
}
@override
void run() {
final hash = sha256.convert(data);
if (hex.encode(hash.bytes) != expected) {
throw 'Incorrect HASH computed.';
}
}
}
void main() {
SHA256Bench().report();
}
-262
View File
@@ -1,262 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:async';
import 'dart:convert';
import 'dart:isolate';
// (Same data as used in our other Json* benchmarks)
final data =
'{"summary":{"turnover":0.3736,"correlation2":0.'
'7147,"concentration":0.3652,"beta":0.8814,"totalValue":1.3'
'091078259E8,"correlation":0.7217},"watchlist":[],"shortCash'
'":-1611000,"holdings":[{"type":"LONG","commission":1040'
',"cost":9001920,"quantity":26000,"lots":[{"marketCap":"'
'L","industry":"TECHNOLOGY","style":"G","buyDate":"20'
'08-10-08 13:44:20.000","quantity":8000},{"marketCap":"L",'
'"industry":"TECHNOLOGY","style":"G","buyDate":"2008-1'
'0-15 13:28:02.000","quantity":18000}],"stock":"GOOG"},{"'
'type":"LONG","commission":8000,"cost":4672000,"quantity'
'":200000,"lots":[{"marketCap":"L","industry":"TECHNOLO'
'GY","style":"G","buyDate":"2008-10-15 13:28:54.000","q'
'uantity":200000}],"stock":"MSFT"},{"type":"LONG","comm'
'ission":21877,"cost":1.001592313E7,"quantity":546919,"lots'
'":[{"marketCap":"L","industry":"FINANCIAL","style":"'
'G","buyDate":"2008-08-01 09:50:17.000","quantity":103092}'
',{"marketCap":"L","industry":"FINANCIAL","style":"G"'
',"buyDate":"2008-08-18 10:31:34.000","quantity":49950},{"'
'marketCap":"L","industry":"FINANCIAL","style":"G","b'
'uyDate":"2008-08-29 09:35:22.000","quantity":45045},{"mark'
'etCap":"L","industry":"FINANCIAL","style":"G","buyDa'
'te":"2008-09-15 09:40:32.000","quantity":48400},{"marketCa'
'p":"L","industry":"FINANCIAL","style":"G","buyDate"'
':"2008-10-06 11:21:50.000","quantity":432},{"marketCap":"'
'L","industry":"FINANCIAL","style":"G","buyDate":"200'
'8-10-15 13:30:05.000","quantity":300000}],"stock":"UBS"},'
'{"type":"LONG","commission":4000,"cost":6604849.1,"quan'
'tity":122741,"lots":[{"marketCap":"L","industry":"SERV'
'ICES","style":"V","buyDate":"2008-04-26 04:44:34.000",'
'"quantity":22741},{"marketCap":"L","industry":"SERVICES'
'","style":"V","buyDate":"2008-10-15 13:31:02.000","qua'
'ntity":100000}],"stock":"V"},{"type":"LONG","commissio'
'n":2805,"cost":5005558.25,"quantity":70121,"lots":[{"mar'
'ketCap":"M","industry":"RETAIL","style":"G","buyDate'
'":"2008-10-10 10:48:36.000","quantity":121},{"marketCap":'
'"M","industry":"RETAIL","style":"G","buyDate":"2008'
'-10-15 13:33:44.000","quantity":70000}],"stock":"LDG"},{'
'"type":"LONG","commission":10000,"cost":5382500,"quanti'
'ty":250000,"lots":[{"marketCap":"L","industry":"RETAIL'
'","style":"V","buyDate":"2008-10-15 13:34:30.000","qua'
'ntity":250000}],"stock":"SWY"},{"type":"LONG","commiss'
'ion":1120,"cost":1240960,"quantity":28000,"lots":[{"mark'
'etCap":"u","industry":"ETF","style":"B","buyDate":'
'"2008-10-15 15:57:39.000","quantity":28000}],"stock":"OIL'
'"},{"type":"LONG","commission":400,"cost":236800,"quan'
'tity":10000,"lots":[{"marketCap":"M","industry":"UTILI'
'TIES_AND_ENERGY","style":"G","buyDate":"2008-10-15 15:58'
':03.000","quantity":10000}],"stock":"COG"},{"type":"LO'
'NG","commission":3200,"cost":1369600,"quantity":80000,"l'
'ots":[{"marketCap":"S","industry":"UTILITIES_AND_ENERGY'
'","style":"G","buyDate":"2008-10-15 15:58:32.000","qua'
'ntity":80000}],"stock":"CRZO"},{"type":"LONG","commiss'
'ion":429,"cost":108164.8,"quantity":10720,"lots":[{"mark'
'etCap":"u","industry":"FINANCIAL","style":"V","buyDa'
'te":"2008-10-16 09:37:06.000","quantity":10720}],"stock":'
'"FGI"},{"type":"LONG","commission":1080,"cost":494910,'
'"quantity":27000,"lots":[{"marketCap":"L","industry":'
'"RETAIL","style":"V","buyDate":"2008-10-16 09:37:06.000'
'","quantity":27000}],"stock":"LOW"},{"type":"LONG","'
'commission":4080,"cost":4867440,"quantity":102000,"lots":'
'[{"marketCap":"L","industry":"HEALTHCARE","style":"V'
'","buyDate":"2008-10-16 09:37:06.000","quantity":102000}]'
',"stock":"AMGN"},{"type":"SHORT","commission":4000,"'
'cost":-1159000,"quantity":-100000,"lots":[{"marketCap":'
'"L","industry":"TECHNOLOGY","style":"V","buyDate":'
'"2008-10-16 09:37:06.000","quantity":-100000}],"stock":"'
'AMAT"},{"type":"LONG","commission":2,"cost":5640002,"'
'quantity":50,"lots":[{"marketCap":"L","industry":"FIN'
'ANCIAL","style":"B","buyDate":"2008-10-16 09:37:06.000'
'","quantity":50}],"stock":"BRKA"},{"type":"SHORT","'
'commission":4000,"cost":-436000,"quantity":-100000,"lots'
'":[{"marketCap":"M","industry":"TRANSPORTATION","styl'
'e":"G","buyDate":"2008-10-16 09:37:06.000","quantity":-'
'100000}],"stock":"JBLU"},{"type":"LONG","commission":8'
'000,"cost":1.1534E7,"quantity":200000,"lots":[{"marketCap'
'":"S","industry":"FINANCIAL","style":"G","buyDate":'
'"2008-10-16 14:35:24.000","quantity":200000}],"stock":"US'
'O"},{"type":"LONG","commission":4000,"cost":1.0129E7,"'
'quantity":100000,"lots":[{"marketCap":"L","industry":"'
'TECHNOLOGY","style":"G","buyDate":"2008-10-15 13:28:26.0'
'00","quantity":50000},{"marketCap":"L","industry":"TEC'
'HNOLOGY","style":"G","buyDate":"2008-10-17 09:33:09.000'
'","quantity":50000}],"stock":"AAPL"},{"type":"LONG",'
'"commission":1868,"cost":9971367.2,"quantity":54280,"lots'
'":[{"marketCap":"L","industry":"SERVICES","style":"G'
'","buyDate":"2008-04-26 04:44:34.000","quantity":7580},{'
'"marketCap":"L","industry":"SERVICES","style":"G","'
'buyDate":"2008-05-29 09:50:28.000","quantity":7500},{"mark'
'etCap":"L","industry":"SERVICES","style":"G","buyDat'
'e":"2008-10-15 13:30:38.000","quantity":33000},{"marketCap'
'":"L","industry":"SERVICES","style":"G","buyDate":'
'"2008-10-17 09:33:09.000","quantity":6200}],"stock":"MA"'
'}],"longCash":4.600368106E7,"ownerId":8,"pendingOrders":[{'
'"total":487000,"type":"cover","subtotal":483000,"price'
'":4.83,"commission":4000,"date":"2008-10-17 23:56:06.000"'
',"quantity":100000,"expires":"2008-10-20 16:00:00.000","s'
'tock":"JBLU","id":182375},{"total":6271600,"type":"buy'
'","subtotal":6270000,"price":156.75,"commission":1600,"d'
'ate":"2008-10-17 23:56:40.000","quantity":40000,"expires"'
':"2008-10-20 16:00:00.000","stock":"MA","id":182376}],"'
'inceptionDate":"2008-04-26 04:44:29.000","withdrawals":0,"'
'id":219948,"deposits":0}';
class SendPortBenchmark {
final BenchmarkConfig config;
ReceivePort port;
StreamIterator it;
double usPerSend = 0.0;
double usPerReceive = 0.0;
SendPortBenchmark(this.config);
// Runs warmup phase, runs benchmark and reports result.
Future report() async {
port = ReceivePort();
it = StreamIterator(port);
// Warmup for 100 ms.
await measureFor(const Duration(milliseconds: 200));
// Run benchmark for 2 seconds.
//
// Sets [usPerSend] and [usPerReceive] as side-effect.
await measureFor(const Duration(seconds: 2));
// Report result.
print('SendPort.Send.${config.name}(RunTimeRaw): $usPerSend us.');
print('SendPort.Receive.${config.name}(RunTimeRaw): $usPerReceive us.');
await it.cancel();
port.close();
}
Future measureFor(Duration duration) async {
final durationInMicroseconds = duration.inMicroseconds;
int sumSendUs = 0;
int sumReceiveUs = 0;
final sw = Stopwatch()..start();
int numberOfSendReceives = 0;
int lastUs = 0;
int currentUs = 0;
do {
// Send & measure time
port.sendPort.send(config.data);
currentUs = sw.elapsedMicroseconds;
sumSendUs += currentUs - lastUs;
lastUs = currentUs;
// Receive & measure time
await it.moveNext();
it.current;
currentUs = sw.elapsedMicroseconds;
sumReceiveUs += currentUs - lastUs;
lastUs = currentUs;
numberOfSendReceives++;
} while (lastUs < durationInMicroseconds);
usPerSend = sumSendUs / numberOfSendReceives;
usPerReceive = sumReceiveUs / numberOfSendReceives;
}
}
class TreeNode {
@pragma('vm:entry-point') // Prevent tree shaking of this field.
final TreeNode left;
@pragma('vm:entry-point') // Prevent tree shaking of this field.
final TreeNode right;
@pragma('vm:entry-point') // Prevent tree shaking of this field.
final int value;
TreeNode(this.left, this.right, this.value);
}
TreeNode generateBinaryTreeOfDepth(int depth) {
int i = 0;
TreeNode gen(int depth) {
if (depth == 0) return TreeNode(null, null, i++);
return TreeNode(gen(depth - 1), gen(depth - 1), i++);
}
return gen(depth);
}
class BenchmarkConfig {
final String name;
final dynamic data;
BenchmarkConfig(this.name, this.data);
}
Future<void> main(args) async {
final String json5KB = data;
final json5KBDecoded = json.decode(json5KB);
assert(json5KB.length == 5534);
final json400B = json.encode(json5KBDecoded['pendingOrders']);
final json400BDecoded = json.decode(json400B);
assert(json400B.length == 390);
final String json50KB = json.encode({
'1': [json5KBDecoded, json5KBDecoded, json5KBDecoded, json5KBDecoded],
'2': [json5KBDecoded, json5KBDecoded, json5KBDecoded, json5KBDecoded],
'3': json5KBDecoded,
});
final json50KBDecoded = json.decode(json50KB);
assert(json50KB.length == 49814);
final String json500KB = json.encode({
'1': [json50KBDecoded, json50KBDecoded, json50KBDecoded, json50KBDecoded],
'2': [json50KBDecoded, json50KBDecoded, json50KBDecoded, json50KBDecoded],
'3': [json50KBDecoded, json50KBDecoded],
});
final json500KBDecoded = json.decode(json500KB);
assert(json500KB.length == 498169);
final String json5MB = json.encode({
'1': [json500KBDecoded, json500KBDecoded, json500KBDecoded],
'2': [json500KBDecoded, json500KBDecoded, json500KBDecoded],
'3': [json500KBDecoded, json500KBDecoded, json500KBDecoded],
'4': json500KBDecoded,
});
final json5MBDecoded = json.decode(json5MB);
assert(json5MB.length == 4981723);
final configs = <BenchmarkConfig>[
BenchmarkConfig('Nop', 1),
BenchmarkConfig('Json.400B', json400BDecoded),
BenchmarkConfig('Json.5KB', json5KBDecoded),
BenchmarkConfig('Json.50KB', json50KBDecoded),
BenchmarkConfig('Json.500KB', json500KBDecoded),
BenchmarkConfig('Json.5MB', json5MBDecoded),
BenchmarkConfig('BinaryTree.2', generateBinaryTreeOfDepth(2)),
BenchmarkConfig('BinaryTree.4', generateBinaryTreeOfDepth(4)),
BenchmarkConfig('BinaryTree.6', generateBinaryTreeOfDepth(6)),
BenchmarkConfig('BinaryTree.8', generateBinaryTreeOfDepth(8)),
BenchmarkConfig('BinaryTree.10', generateBinaryTreeOfDepth(10)),
BenchmarkConfig('BinaryTree.12', generateBinaryTreeOfDepth(12)),
BenchmarkConfig('BinaryTree.14', generateBinaryTreeOfDepth(14)),
];
for (final config in configs) {
await SendPortBenchmark(config).report();
}
}
@@ -1,35 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// A Dart implementation of two computation kernels used for skeletal
/// animation.
// @dart=2.9
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:vector_math/vector_math_operations.dart';
void main() {
SkeletalAnimation().report();
}
class SkeletalAnimation extends BenchmarkBase {
SkeletalAnimation() : super('SkeletalAnimation');
final Float32List A = Float32List(16);
final Float32List B = Float32List(16);
final Float32List C = Float32List(16);
final Float32List D = Float32List(4);
final Float32List E = Float32List(4);
@override
void run() {
for (int i = 0; i < 100; i++) {
Matrix44Operations.multiply(C, 0, A, 0, B, 0);
Matrix44Operations.transform4(E, 0, A, 0, D, 0);
}
}
}
@@ -1,35 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// A Dart implementation of two computation kernels used for skeletal
/// animation. SIMD version.
// @dart=2.9
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:vector_math/vector_math_operations.dart';
void main() {
SkeletalAnimationSIMD().report();
}
class SkeletalAnimationSIMD extends BenchmarkBase {
SkeletalAnimationSIMD() : super('SkeletalAnimationSIMD');
final Float32x4List A = Float32x4List(4);
final Float32x4List B = Float32x4List(4);
final Float32x4List C = Float32x4List(4);
final Float32x4List D = Float32x4List(1);
final Float32x4List E = Float32x4List(1);
@override
void run() {
for (int i = 0; i < 100; i++) {
Matrix44SIMDOperations.multiply(C, 0, A, 0, B, 0);
Matrix44SIMDOperations.transform4(E, 0, A, 0, D, 0);
}
}
}
@@ -1,31 +0,0 @@
# SoundSplayTreeSieve
The SoundSplayTreeSieve benchmark reports the runtime of the `sieve9` Golem benchmark
for a `SplayTreeSet` from `dart:collection` and a `SoundSplayTreeSet` that
declares variance modifiers for its type parameters.
## Running the benchmark
These are instructions for running the benchmark, assuming you are in the `sdk`
directory.
These benchmarks print a result similar to this (with varying runtimes):
```
CollectionSieves-SplayTreeSet-removeLoop(RunTime): 4307.52688172043 us.
CollectionSieves-SoundSplayTreeSet-removeLoop(RunTime): 4344.902386117137 us.
```
**Dart2JS**
```
$ sdk/bin/dart2js_developer benchmarks/SoundSplayTreeSieve/dart/SoundSplayTreeSieve.dart --enable-experiment=variance --out=soundsplay_d2js.js
$ third_party/d8/linux/d8 soundsplay_d2js.js
```
**Dart2JS (Omit implicit checks)**
```
$ sdk/bin/dart2js_developer benchmarks/SoundSplayTreeSieve/dart/SoundSplayTreeSieve.dart --enable-experiment=variance --omit-implicit-checks --out=soundsplay_d2js_omit.js --lax-runtime-type-to-string
$ third_party/d8/linux/d8 soundsplay_d2js_omit.js
```
**DDK**
```
$ pkg/dev_compiler/tool/ddb -d -r chrome --enable-experiment=variance -k benchmarks/SoundSplayTreeSieve/dart/SoundSplayTreeSieve.dart
```
@@ -1,119 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:collection';
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'sound_splay_tree.dart';
List<int> sieve(List<int> initialCandidates) {
final candidates = SplayTreeSet<int>.from(initialCandidates);
final int last = candidates.last;
final primes = <int>[];
// ignore: literal_only_boolean_expressions
while (true) {
final int prime = candidates.first;
if (prime * prime > last) break;
primes.add(prime);
for (int i = prime; i <= last; i += prime) {
candidates.remove(i);
}
}
return primes..addAll(candidates);
}
List<int> sieveSound(List<int> initialCandidates) {
final candidates = SoundSplayTreeSet<int>.from(initialCandidates);
final int last = candidates.last;
final primes = <int>[];
// ignore: literal_only_boolean_expressions
while (true) {
final int prime = candidates.first;
if (prime * prime > last) break;
primes.add(prime);
for (int i = prime; i <= last; i += prime) {
candidates.remove(i);
}
}
return primes..addAll(candidates);
}
/// Returns a list of integers from [first] to [last], both inclusive.
List<int> range(int first, int last) {
return List<int>.generate(last - first + 1, (int i) => i + first);
}
int id(int x) => x;
int add1(int i) => 1 + i;
bool isEven(int i) => i.isEven;
void exercise(Iterable<int> hello) {
if (hello.toList().length != 5) throw 'x1';
if (List.from(hello).length != 5) throw 'x1';
if (Set.from(hello).length != 4) throw 'x1';
if (List<int>.from(hello).where(isEven).length != 3) throw 'x1';
if (hello.where(isEven).length != 3) throw 'x1';
if (hello.map(add1).where(isEven).length != 2) throw 'x1';
if (hello.where(isEven).map(add1).length != 3) throw 'x1';
}
void busyWork() {
// A lot of busy-work calling map/where/toList/List.from to ensure the core
// library is used with some degree of polymorphism.
final L1 = 'hello'.codeUnits;
final L2 = Uint16List(5)..setRange(0, 5, L1);
final L3 = Uint32List(5)..setRange(0, 5, L1);
exercise(L1);
exercise(L2);
exercise(L3);
exercise(UnmodifiableListView<int>(L1));
exercise(UnmodifiableListView<int>(L2));
exercise(UnmodifiableListView<int>(L3));
exercise(L1.asMap().values);
exercise(L1.toList().asMap().values);
final M1 = Map<String, int>.fromIterables(<String>[
'a',
'b',
'c',
'd',
'e',
], L1);
final M2 = const <String, int>{
'a': 104,
'b': 101,
'c': 108,
'd': 108,
'e': 111,
};
exercise(M1.values);
exercise(M2.values);
}
main() {
final benchmarks = [
Base(sieve, 'CollectionSieves-SplayTreeSet-removeLoop'),
Base(sieveSound, 'CollectionSieves-SoundSplayTreeSet-removeLoop'),
];
for (int i = 0; i < 10; i++) {
busyWork();
for (var bm in benchmarks) {
bm.run();
}
}
for (var bm in benchmarks) {
bm.report();
}
}
class Base extends BenchmarkBase {
final algorithm;
Base(this.algorithm, String name) : super(name);
static final input = range(2, 5000);
void run() {
final primes = algorithm(input);
if (primes.length != 669) throw 'Wrong result for $name: ${primes.length}';
}
}
@@ -1,26 +0,0 @@
/// Marker interface for [Iterable] subclasses that have an efficient
/// [length] implementation.
// @dart=2.9
abstract class EfficientLengthIterable<T> extends Iterable<T> {
const EfficientLengthIterable();
/// Returns the number of elements in the iterable.
///
/// This is an efficient operation that doesn't require iterating through
/// the elements.
int get length;
}
/// Creates errors throw by [Iterable] when the element count is wrong.
abstract class IterableElementError {
/// Error thrown by, e.g., [Iterable.first] when there is no result.
static StateError noElement() => StateError("No element");
/// Error thrown by, e.g., [Iterable.single] if there are too many results.
static StateError tooMany() => StateError("Too many elements");
/// Error thrown by, e.g., [List.setRange] if there are too few elements.
static StateError tooFew() => StateError("Too few elements");
}
@@ -1,884 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:collection';
import 'iterable.dart';
typedef _Predicate<T> = bool Function(T value);
/// A node in a splay tree. It holds the sorting key and the left
/// and right children in the tree.
class _SoundSplayTreeNode<inout K> {
final K key;
_SoundSplayTreeNode<K> left;
_SoundSplayTreeNode<K> right;
_SoundSplayTreeNode(this.key);
}
/// A node in a splay tree based map.
///
/// A [_SoundSplayTreeNode] that also contains a value
class _SoundSplayTreeMapNode<inout K, inout V> extends _SoundSplayTreeNode<K> {
V value;
_SoundSplayTreeMapNode(K key, this.value) : super(key);
}
/// A splay tree is a self-balancing binary search tree.
///
/// It has the additional property that recently accessed elements
/// are quick to access again.
/// It performs basic operations such as insertion, look-up and
/// removal, in O(log(n)) amortized time.
/// TODO(kallentu): Add a variance modifier to the Node type parameter.
abstract class _SoundSplayTree<inout K, Node extends _SoundSplayTreeNode<K>> {
// The root node of the splay tree. It will contain either the last
// element inserted or the last element looked up.
Node get _root;
set _root(Node newValue);
// The dummy node used when performing a splay on the tree. Reusing it
// avoids allocating a node each time a splay is performed.
Node get _dummy;
// Number of elements in the splay tree.
int _count = 0;
/// Counter incremented whenever the keys in the map changes.
///
/// Used to detect concurrent modifications.
int _modificationCount = 0;
/// Counter incremented whenever the tree structure changes.
///
/// Used to detect that an in-place traversal cannot use
/// cached information that relies on the tree structure.
int _splayCount = 0;
/// The comparator that is used for this splay tree.
Comparator<K> get _comparator;
/// The predicate to determine that a given object is a valid key.
_Predicate get _validKey;
/// Comparison used to compare keys.
int _compare(K key1, K key2);
/// Perform the splay operation for the given key. Moves the node with
/// the given key to the top of the tree. If no node has the given
/// key, the last node on the search path is moved to the top of the
/// tree. This is the simplified top-down splaying algorithm from:
/// "Self-adjusting Binary Search Trees" by Sleator and Tarjan.
///
/// Returns the result of comparing the new root of the tree to [key].
/// Returns -1 if the table is empty.
int _splay(K key) {
if (_root == null) return -1;
// The right child of the dummy node will hold
// the L tree of the algorithm. The left child of the dummy node
// will hold the R tree of the algorithm. Using a dummy node, left
// and right will always be nodes and we avoid special cases.
Node left = _dummy;
Node right = _dummy;
Node current = _root;
int comp;
while (true) {
comp = _compare(current.key, key);
if (comp > 0) {
if (current.left == null) break;
comp = _compare(current.left.key, key);
if (comp > 0) {
// Rotate right.
_SoundSplayTreeNode<K> tmp = current.left;
current.left = tmp.right;
tmp.right = current;
current = tmp;
if (current.left == null) break;
}
// Link right.
right.left = current;
right = current;
current = current.left;
} else if (comp < 0) {
if (current.right == null) break;
comp = _compare(current.right.key, key);
if (comp < 0) {
// Rotate left.
Node tmp = current.right;
current.right = tmp.left;
tmp.left = current;
current = tmp;
if (current.right == null) break;
}
// Link left.
left.right = current;
left = current;
current = current.right;
} else {
break;
}
}
// Assemble.
left.right = current.left;
right.left = current.right;
current.left = _dummy.right;
current.right = _dummy.left;
_root = current;
_dummy.right = null;
_dummy.left = null;
_splayCount++;
return comp;
}
// Emulates splaying with a key that is smaller than any in the subtree
// anchored at [node].
// and that node is returned. It should replace the reference to [node]
// in any parent tree or root pointer.
Node _splayMin(Node node) {
Node current = node;
while (current.left != null) {
Node left = current.left;
current.left = left.right;
left.right = current;
current = left;
}
return current;
}
// Emulates splaying with a key that is greater than any in the subtree
// anchored at [node].
// After this, the largest element in the tree is the root of the subtree,
// and that node is returned. It should replace the reference to [node]
// in any parent tree or root pointer.
Node _splayMax(Node node) {
Node current = node;
while (current.right != null) {
Node right = current.right;
current.right = right.left;
right.left = current;
current = right;
}
return current;
}
Node _remove(K key) {
if (_root == null) return null;
int comp = _splay(key);
if (comp != 0) return null;
Node result = _root;
_count--;
// assert(_count >= 0);
if (_root.left == null) {
_root = _root.right;
} else {
Node right = _root.right;
// Splay to make sure that the new root has an empty right child.
_root = _splayMax(_root.left);
// Insert the original right child as the right child of the new
// root.
_root.right = right;
}
_modificationCount++;
return result;
}
/// Adds a new root node with the given [key] or [value].
///
/// The [comp] value is the result of comparing the existing root's key
/// with key.
void _addNewRoot(Node node, int comp) {
_count++;
_modificationCount++;
if (_root == null) {
_root = node;
return;
}
// assert(_count >= 0);
if (comp < 0) {
node.left = _root;
node.right = _root.right;
_root.right = null;
} else {
node.right = _root;
node.left = _root.left;
_root.left = null;
}
_root = node;
}
Node get _first {
if (_root == null) return null;
_root = _splayMin(_root);
return _root;
}
Node get _last {
if (_root == null) return null;
_root = _splayMax(_root);
return _root;
}
void _clear() {
_root = null;
_count = 0;
_modificationCount++;
}
}
class _TypeTest<T> {
bool test(v) => v is T;
}
int _dynamicCompare(dynamic a, dynamic b) => Comparable.compare(a, b);
Comparator<K> _defaultCompare<K>() {
// If K <: Comparable, then we can just use Comparable.compare
// with no casts.
Object compare = Comparable.compare;
if (compare is Comparator<K>) {
return compare;
}
// Otherwise wrap and cast the arguments on each call.
return _dynamicCompare;
}
/// A [Map] of objects that can be ordered relative to each other.
///
/// The map is based on a self-balancing binary tree. It allows most operations
/// in amortized logarithmic time.
///
/// Keys of the map are compared using the `compare` function passed in
/// the constructor, both for ordering and for equality.
/// If the map contains only the key `a`, then `map.containsKey(b)`
/// will return `true` if and only if `compare(a, b) == 0`,
/// and the value of `a == b` is not even checked.
/// If the compare function is omitted, the objects are assumed to be
/// [Comparable], and are compared using their [Comparable.compareTo] method.
/// Non-comparable objects (including `null`) will not work as keys
/// in that case.
///
/// To allow calling [operator []], [remove] or [containsKey] with objects
/// that are not supported by the `compare` function, an extra `isValidKey`
/// predicate function can be supplied. This function is tested before
/// using the `compare` function on an argument value that may not be a [K]
/// value. If omitted, the `isValidKey` function defaults to testing if the
/// value is a [K].
class SoundSplayTreeMap<inout K, inout V> extends _SoundSplayTree<K, _SoundSplayTreeMapNode<K, V>>
with MapMixin<K, V> {
_SoundSplayTreeMapNode<K, V> _root;
final _SoundSplayTreeMapNode<K, V> _dummy = _SoundSplayTreeMapNode<K, V>(null, null);
Comparator<K> _comparator;
_Predicate _validKey;
SoundSplayTreeMap([int compare(K key1, K key2), bool isValidKey(potentialKey)])
: _comparator = compare ?? _defaultCompare<K>(),
_validKey = isValidKey ?? ((v) => v is K);
/// Creates a [SoundSplayTreeMap] that contains all key/value pairs of [other].
///
/// The keys must all be instances of [K] and the values of [V].
/// The [other] map itself can have any type.
factory SoundSplayTreeMap.from(Map other,
[int compare(K key1, K key2), bool isValidKey(potentialKey)]) {
SoundSplayTreeMap<K, V> result = SoundSplayTreeMap<K, V>(compare, isValidKey);
other.forEach((k, v) {
result[k] = v;
});
return result;
}
/// Creates a [SoundSplayTreeMap] that contains all key/value pairs of [other].
factory SoundSplayTreeMap.of(Map<K, V> other,
[int compare(K key1, K key2), bool isValidKey(potentialKey)]) =>
SoundSplayTreeMap<K, V>(compare, isValidKey)..addAll(other);
/// Creates a [SoundSplayTreeMap] where the keys and values are computed from the
/// [iterable].
///
/// For each element of the [iterable] this constructor computes a key/value
/// pair, by applying [key] and [value] respectively.
///
/// The keys of the key/value pairs do not need to be unique. The last
/// occurrence of a key will simply overwrite any previous value.
///
/// If no functions are specified for [key] and [value] the default is to
/// use the iterable value itself.
factory SoundSplayTreeMap.fromIterable(Iterable iterable,
{K key(element),
V value(element),
int compare(K key1, K key2),
bool isValidKey(potentialKey)}) {
SoundSplayTreeMap<K, V> map = SoundSplayTreeMap<K, V>(compare, isValidKey);
fillMapWithMappedIterable(map, iterable, key, value);
return map;
}
static _id(x) => x;
static void fillMapWithMappedIterable(
Map map, Iterable iterable, key(element), value(element)) {
key ??= _id;
value ??= _id;
for (var element in iterable) {
map[key(element)] = value(element);
}
}
static void fillMapWithIterables(Map map, Iterable keys, Iterable values) {
Iterator keyIterator = keys.iterator;
Iterator valueIterator = values.iterator;
bool hasNextKey = keyIterator.moveNext();
bool hasNextValue = valueIterator.moveNext();
while (hasNextKey && hasNextValue) {
map[keyIterator.current] = valueIterator.current;
hasNextKey = keyIterator.moveNext();
hasNextValue = valueIterator.moveNext();
}
if (hasNextKey || hasNextValue) {
throw ArgumentError("Iterables do not have same length.");
}
}
/// Creates a [SoundSplayTreeMap] associating the given [keys] to [values].
///
/// This constructor iterates over [keys] and [values] and maps each element
/// of [keys] to the corresponding element of [values].
///
/// If [keys] contains the same object multiple times, the last occurrence
/// overwrites the previous value.
///
/// It is an error if the two [Iterable]s don't have the same length.
factory SoundSplayTreeMap.fromIterables(Iterable<K> keys, Iterable<V> values,
[int compare(K key1, K key2), bool isValidKey(potentialKey)]) {
SoundSplayTreeMap<K, V> map = SoundSplayTreeMap<K, V>(compare, isValidKey);
fillMapWithIterables(map, keys, values);
return map;
}
int _compare(K key1, K key2) => _comparator(key1, key2);
SoundSplayTreeMap._internal();
V operator [](Object key) {
if (!_validKey(key)) return null;
if (_root != null) {
int comp = _splay(key);
if (comp == 0) {
return _root.value;
}
}
return null;
}
V remove(Object key) {
if (!_validKey(key)) return null;
_SoundSplayTreeMapNode<K, V> mapRoot = _remove(key);
if (mapRoot != null) return mapRoot.value;
return null;
}
void operator []=(K key, V value) {
if (key == null) throw ArgumentError(key);
// Splay on the key to move the last node on the search path for
// the key to the root of the tree.
int comp = _splay(key);
if (comp == 0) {
_root.value = value;
return;
}
_addNewRoot(_SoundSplayTreeMapNode(key, value), comp);
}
V putIfAbsent(K key, V ifAbsent()) {
if (key == null) throw ArgumentError(key);
int comp = _splay(key);
if (comp == 0) {
return _root.value;
}
int modificationCount = _modificationCount;
int splayCount = _splayCount;
V value = ifAbsent();
if (modificationCount != _modificationCount) {
throw ConcurrentModificationError(this);
}
if (splayCount != _splayCount) {
comp = _splay(key);
// Key is still not there, otherwise _modificationCount would be changed.
assert(comp != 0);
}
_addNewRoot(_SoundSplayTreeMapNode(key, value), comp);
return value;
}
void addAll(Map<K, V> other) {
other.forEach((K key, V value) {
this[key] = value;
});
}
bool get isEmpty {
return (_root == null);
}
bool get isNotEmpty => !isEmpty;
void forEach(void f(K key, V value)) {
Iterator<_SoundSplayTreeNode<K>> nodes = _SoundSplayTreeNodeIterator<K>(this);
while (nodes.moveNext()) {
_SoundSplayTreeMapNode<K, V> node = nodes.current;
f(node.key, node.value);
}
}
int get length {
return _count;
}
void clear() {
_clear();
}
bool containsKey(Object key) {
return _validKey(key) && _splay(key) == 0;
}
bool containsValue(Object value) {
int initialSplayCount = _splayCount;
bool visit(_SoundSplayTreeMapNode<K, V> node) {
while (node != null) {
if (node.value == value) return true;
if (initialSplayCount != _splayCount) {
throw ConcurrentModificationError(this);
}
if (node.right != null && visit(node.right)) return true;
node = node.left;
}
return false;
}
return visit(_root);
}
Iterable<K> get keys => _SoundSplayTreeKeyIterable<K>(this);
Iterable<V> get values => _SoundSplayTreeValueIterable<K, V>(this);
/// Get the first key in the map. Returns [:null:] if the map is empty.
K firstKey() {
if (_root == null) return null;
return _first.key;
}
/// Get the last key in the map. Returns [:null:] if the map is empty.
K lastKey() {
if (_root == null) return null;
return _last.key;
}
/// Get the last key in the map that is strictly smaller than [key]. Returns
/// [:null:] if no key was not found.
K lastKeyBefore(K key) {
if (key == null) throw ArgumentError(key);
if (_root == null) return null;
int comp = _splay(key);
if (comp < 0) return _root.key;
_SoundSplayTreeNode<K> node = _root.left;
if (node == null) return null;
while (node.right != null) {
node = node.right;
}
return node.key;
}
/// Get the first key in the map that is strictly larger than [key]. Returns
/// [:null:] if no key was not found.
K firstKeyAfter(K key) {
if (key == null) throw ArgumentError(key);
if (_root == null) return null;
int comp = _splay(key);
if (comp > 0) return _root.key;
_SoundSplayTreeNode<K> node = _root.right;
if (node == null) return null;
while (node.left != null) {
node = node.left;
}
return node.key;
}
}
abstract class _SoundSplayTreeIterator<inout K, inout T> implements Iterator<T> {
final _SoundSplayTree<K, _SoundSplayTreeNode<K>> _tree;
/// Worklist of nodes to visit.
///
/// These nodes have been passed over on the way down in a
/// depth-first left-to-right traversal. Visiting each node,
/// and their right subtrees will visit the remainder of
/// the nodes of a full traversal.
///
/// Only valid as long as the original tree isn't reordered.
final List<_SoundSplayTreeNode<K>> _workList = <_SoundSplayTreeNode<K>>[];
/// Original modification counter of [_tree].
///
/// Incremented on [_tree] when a key is added or removed.
/// If it changes, iteration is aborted.
///
/// Not final because some iterators may modify the tree knowingly,
/// and they update the modification count in that case.
int _modificationCount;
/// Count of splay operations on [_tree] when [_workList] was built.
///
/// If the splay count on [_tree] increases, [_workList] becomes invalid.
int _splayCount;
/// Current node.
_SoundSplayTreeNode<K> _currentNode;
_SoundSplayTreeIterator(_SoundSplayTree<K, _SoundSplayTreeNode<K>> tree)
: _tree = tree,
_modificationCount = tree._modificationCount,
_splayCount = tree._splayCount {
_findLeftMostDescendant(tree._root);
}
_SoundSplayTreeIterator.startAt(_SoundSplayTree<K, _SoundSplayTreeNode<K>> tree, K startKey)
: _tree = tree,
_modificationCount = tree._modificationCount {
if (tree._root == null) return;
int compare = tree._splay(startKey);
_splayCount = tree._splayCount;
if (compare < 0) {
// Don't include the root, start at the next element after the root.
_findLeftMostDescendant(tree._root.right);
} else {
_workList.add(tree._root);
}
}
T get current {
if (_currentNode == null) return null;
return _getValue(_currentNode);
}
void _findLeftMostDescendant(_SoundSplayTreeNode<K> node) {
while (node != null) {
_workList.add(node);
node = node.left;
}
}
/// Called when the tree structure of the tree has changed.
///
/// This can be caused by a splay operation.
/// If the key-set changes, iteration is aborted before getting
/// here, so we know that the keys are the same as before, it's
/// only the tree that has been reordered.
void _rebuildWorkList(_SoundSplayTreeNode<K> currentNode) {
assert(_workList.isNotEmpty);
_workList.clear();
if (currentNode == null) {
_findLeftMostDescendant(_tree._root);
} else {
_tree._splay(currentNode.key);
_findLeftMostDescendant(_tree._root.right);
assert(_workList.isNotEmpty);
}
}
bool moveNext() {
if (_modificationCount != _tree._modificationCount) {
throw ConcurrentModificationError(_tree);
}
// Picks the next element in the worklist as current.
// Updates the worklist with the left-most path of the current node's
// right-hand child.
// If the worklist is no longer valid (after a splay), it is rebuild
// from scratch.
if (_workList.isEmpty) {
_currentNode = null;
return false;
}
if (_tree._splayCount != _splayCount && _currentNode != null) {
_rebuildWorkList(_currentNode);
}
_currentNode = _workList.removeLast();
_findLeftMostDescendant(_currentNode.right);
return true;
}
T _getValue(_SoundSplayTreeNode<K> node);
}
class _SoundSplayTreeKeyIterable<inout K> extends EfficientLengthIterable<K> {
_SoundSplayTree<K, _SoundSplayTreeNode<K>> _tree;
_SoundSplayTreeKeyIterable(this._tree);
int get length => _tree._count;
bool get isEmpty => _tree._count == 0;
Iterator<K> get iterator => _SoundSplayTreeKeyIterator<K>(_tree);
Set<K> toSet() {
SoundSplayTreeSet<K> set = SoundSplayTreeSet<K>(_tree._comparator, _tree._validKey);
set._count = _tree._count;
set._root = set._copyNode(_tree._root);
return set;
}
}
class _SoundSplayTreeValueIterable<inout K, inout V> extends EfficientLengthIterable<V> {
SoundSplayTreeMap<K, V> _map;
_SoundSplayTreeValueIterable(this._map);
int get length => _map._count;
bool get isEmpty => _map._count == 0;
Iterator<V> get iterator => _SoundSplayTreeValueIterator<K, V>(_map);
}
class _SoundSplayTreeKeyIterator<inout K> extends _SoundSplayTreeIterator<K, K> {
_SoundSplayTreeKeyIterator(_SoundSplayTree<K, _SoundSplayTreeNode<K>> map) : super(map);
K _getValue(_SoundSplayTreeNode<K> node) => node.key;
}
class _SoundSplayTreeValueIterator<inout K, inout V> extends _SoundSplayTreeIterator<K, V> {
_SoundSplayTreeValueIterator(SoundSplayTreeMap<K, V> map) : super(map);
V _getValue(_SoundSplayTreeNode<K> node) {
_SoundSplayTreeMapNode<K, V> mapNode = node;
return mapNode.value;
}
}
class _SoundSplayTreeNodeIterator<inout K>
extends _SoundSplayTreeIterator<K, _SoundSplayTreeNode<K>> {
_SoundSplayTreeNodeIterator(_SoundSplayTree<K, _SoundSplayTreeNode<K>> tree) : super(tree);
_SoundSplayTreeNodeIterator.startAt(
_SoundSplayTree<K, _SoundSplayTreeNode<K>> tree, K startKey)
: super.startAt(tree, startKey);
_SoundSplayTreeNode<K> _getValue(_SoundSplayTreeNode<K> node) => node;
}
/// A [Set] of objects that can be ordered relative to each other.
///
/// The set is based on a self-balancing binary tree. It allows most operations
/// in amortized logarithmic time.
///
/// Elements of the set are compared using the `compare` function passed in
/// the constructor, both for ordering and for equality.
/// If the set contains only an object `a`, then `set.contains(b)`
/// will return `true` if and only if `compare(a, b) == 0`,
/// and the value of `a == b` is not even checked.
/// If the compare function is omitted, the objects are assumed to be
/// [Comparable], and are compared using their [Comparable.compareTo] method.
/// Non-comparable objects (including `null`) will not work as an element
/// in that case.
class SoundSplayTreeSet<inout E> extends _SoundSplayTree<E, _SoundSplayTreeNode<E>>
with IterableMixin<E>, SetMixin<E> {
_SoundSplayTreeNode<E> _root;
final _SoundSplayTreeNode<E> _dummy = _SoundSplayTreeNode<E>(null);
Comparator<E> _comparator;
_Predicate _validKey;
/// Create a new [SoundSplayTreeSet] with the given compare function.
///
/// If the [compare] function is omitted, it defaults to [Comparable.compare],
/// and the elements must be comparable.
///
/// A provided `compare` function may not work on all objects. It may not even
/// work on all `E` instances.
///
/// For operations that add elements to the set, the user is supposed to not
/// pass in objects that doesn't work with the compare function.
///
/// The methods [contains], [remove], [lookup], [removeAll] or [retainAll]
/// are typed to accept any object(s), and the [isValidKey] test can used to
/// filter those objects before handing them to the `compare` function.
///
/// If [isValidKey] is provided, only values satisfying `isValidKey(other)`
/// are compared using the `compare` method in the methods mentioned above.
/// If the `isValidKey` function returns false for an object, it is assumed to
/// not be in the set.
///
/// If omitted, the `isValidKey` function defaults to checking against the
/// type parameter: `other is E`.
SoundSplayTreeSet([int compare(E key1, E key2), bool isValidKey(potentialKey)])
: _comparator = compare ?? _defaultCompare<E>(),
_validKey = isValidKey ?? ((v) => v is E);
/// Creates a [SoundSplayTreeSet] that contains all [elements].
///
/// The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
///
/// All the [elements] should be instances of [E] and valid arguments to
/// [compare].
/// The `elements` iterable itself may have any element type, so this
/// constructor can be used to down-cast a `Set`, for example as:
/// ```dart
/// Set<SuperType> superSet = ...;
/// Set<SubType> subSet =
/// new SplayTreeSet<SubType>.from(superSet.whereType<SubType>());
/// ```
factory SoundSplayTreeSet.from(Iterable elements,
[int compare(E key1, E key2), bool isValidKey(potentialKey)]) {
SoundSplayTreeSet<E> result = SoundSplayTreeSet<E>(compare, isValidKey);
for (final element in elements) {
E e = element;
result.add(e);
}
return result;
}
/// Creates a [SoundSplayTreeSet] from [elements].
///
/// The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
///
/// All the [elements] should be valid as arguments to the [compare] function.
factory SoundSplayTreeSet.of(Iterable<E> elements,
[int compare(E key1, E key2), bool isValidKey(potentialKey)]) =>
SoundSplayTreeSet(compare, isValidKey)..addAll(elements);
Set<T> _newSet<T>() =>
SoundSplayTreeSet<T>((T a, T b) => _comparator(a as E, b as E), _validKey);
Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newSet);
int _compare(E e1, E e2) => _comparator(e1, e2);
// From Iterable.
Iterator<E> get iterator => _SoundSplayTreeKeyIterator<E>(this);
int get length => _count;
bool get isEmpty => _root == null;
bool get isNotEmpty => _root != null;
E get first {
if (_count == 0) throw IterableElementError.noElement();
return _first.key;
}
E get last {
if (_count == 0) throw IterableElementError.noElement();
return _last.key;
}
E get single {
if (_count == 0) throw IterableElementError.noElement();
if (_count > 1) throw IterableElementError.tooMany();
return _root.key;
}
// From Set.
bool contains(Object element) {
return _validKey(element) && _splay(element) == 0;
}
bool add(E element) {
int compare = _splay(element);
if (compare == 0) return false;
_addNewRoot(_SoundSplayTreeNode(element), compare);
return true;
}
bool remove(Object object) {
if (!_validKey(object)) return false;
return _remove(object) != null;
}
void addAll(Iterable<E> elements) {
for (E element in elements) {
int compare = _splay(element);
if (compare != 0) {
_addNewRoot(_SoundSplayTreeNode(element), compare);
}
}
}
void removeAll(Iterable<Object> elements) {
for (Object element in elements) {
if (_validKey(element)) _remove(element);
}
}
void retainAll(Iterable<Object> elements) {
// Build a set with the same sense of equality as this set.
SoundSplayTreeSet<E> retainSet = SoundSplayTreeSet<E>(_comparator, _validKey);
int modificationCount = _modificationCount;
for (Object object in elements) {
if (modificationCount != _modificationCount) {
// The iterator should not have side effects.
throw ConcurrentModificationError(this);
}
// Equivalent to this.contains(object).
if (_validKey(object) && _splay(object) == 0) {
retainSet.add(_root.key);
}
}
// Take over the elements from the retained set, if it differs.
if (retainSet._count != _count) {
_root = retainSet._root;
_count = retainSet._count;
_modificationCount++;
}
}
E lookup(Object object) {
if (!_validKey(object)) return null;
int comp = _splay(object);
if (comp != 0) return null;
return _root.key;
}
Set<E> intersection(Set<Object> other) {
Set<E> result = SoundSplayTreeSet<E>(_comparator, _validKey);
for (E element in this) {
if (other.contains(element)) result.add(element);
}
return result;
}
Set<E> difference(Set<Object> other) {
Set<E> result = SoundSplayTreeSet<E>(_comparator, _validKey);
for (E element in this) {
if (!other.contains(element)) result.add(element);
}
return result;
}
Set<E> union(Set<E> other) {
return _clone()..addAll(other);
}
SoundSplayTreeSet<E> _clone() {
var set = SoundSplayTreeSet<E>(_comparator, _validKey);
set._count = _count;
set._root = _copyNode(_root);
return set;
}
// Copies the structure of a SplayTree into a new similar structure.
// Works on _SplayTreeMapNode as well, but only copies the keys,
_SoundSplayTreeNode<E> _copyNode(_SoundSplayTreeNode<E> node) {
if (node == null) return null;
return _SoundSplayTreeNode<E>(node.key)
..left = _copyNode(node.left)
..right = _copyNode(node.right);
}
void clear() {
_clear();
}
Set<E> toSet() => _clone();
String toString() => IterableBase.iterableToFullString(this, '{', '}');
}
-88
View File
@@ -1,88 +0,0 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:convert';
import 'dart:io';
import 'package:compiler/src/dart2js.dart' as dart2js;
Future<void> main(List<String> args) async {
if (args.contains('--child')) {
return;
}
// Include dart2js and prevent tree-shaking to make this program have a
// non-trival snapshot size.
if (args.contains('--train')) {
args.remove('--train');
return dart2js.main(args);
}
var tempDir;
var events;
try {
tempDir = await Directory.systemTemp.createTemp();
final timelinePath =
tempDir.uri.resolve('Startup-timeline.json').toFilePath();
final p = await Process.run(Platform.executable, [
...Platform.executableArguments,
'--timeline_recorder=file:$timelinePath',
'--timeline_streams=VM,Isolate,Embedder',
Platform.script.toFilePath(),
'--child',
]);
if (p.exitCode != 0) {
print(p.stdout);
print(p.stderr);
throw 'Child process failed: ${p.exitCode}';
}
events = jsonDecode(await File(timelinePath).readAsString());
} finally {
await tempDir.delete(recursive: true);
}
var mainIsolateId;
for (final event in events) {
if (event['name'] == 'InitializeIsolate' &&
event['args']['isolateName'] == 'main') {
mainIsolateId = event['args']['isolateId'];
}
}
if (mainIsolateId == null) {
throw 'Could not determine main isolate';
}
void report(String name, String isolateId) {
var filtered = events.where((event) => event['name'] == name);
if (isolateId != null) {
filtered = filtered.where(
(event) => event['args']['isolateId'] == isolateId,
);
}
var micros;
final durations = filtered.where((event) => event['ph'] == 'X');
final begins = filtered.where((event) => event['ph'] == 'B');
final ends = filtered.where((event) => event['ph'] == 'E');
if (durations.length == 1 && begins.length == 0 && ends.length == 0) {
micros = durations.single['dur'];
} else if (durations.length == 0 &&
begins.length == 1 &&
ends.length == 1) {
micros = ends.single['ts'] - begins.single['ts'];
} else {
print(durations.toList());
print(begins.toList());
print(ends.toList());
throw '$name is missing or ambiguous';
}
print('Startup.$name(StartupTime): $micros us.');
}
report('CreateIsolateGroupAndSetupHelper', null);
report('InitializeIsolate', mainIsolateId);
report('ReadProgramSnapshot', mainIsolateId);
}
@@ -1,11 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.7
import '../dart/StringPool.dart' as primary;
void main() {
primary.main();
}
@@ -1,11 +0,0 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.7
import '../dart/StringPool100.dart' as primary;
void main() {
primary.main();
}
-879
View File
@@ -1,879 +0,0 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
// Micro-benchmarks for typed data setters and getters.
//
// @dart=2.9
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
//
// Typed constant setters.
//
void doSetInt8(Int8List list) {
for (int i = 0; i < list.length; i++) {
list[i] = 1;
}
}
void doSetUint8(Uint8List list) {
for (int i = 0; i < list.length; i++) {
list[i] = 1;
}
}
void doSetUint8Clamped(Uint8ClampedList list) {
for (int i = 0; i < list.length; i++) {
list[i] = 1;
}
}
void doSetInt16(Int16List list) {
for (int i = 0; i < list.length; i++) {
list[i] = 1;
}
}
void doSetUint16(Uint16List list) {
for (int i = 0; i < list.length; i++) {
list[i] = 1;
}
}
void doSetInt32(Int32List list) {
for (int i = 0; i < list.length; i++) {
list[i] = 1;
}
}
void doSetUint32(Uint32List list) {
for (int i = 0; i < list.length; i++) {
list[i] = 1;
}
}
void doSetInt64(Int64List list) {
for (int i = 0; i < list.length; i++) {
list[i] = 1;
}
}
void doSetUint64(Uint64List list) {
for (int i = 0; i < list.length; i++) {
list[i] = 1;
}
}
void doSetFloat32(Float32List list) {
for (int i = 0; i < list.length; i++) {
list[i] = 1.0;
}
}
void doSetFloat64(Float64List list) {
for (int i = 0; i < list.length; i++) {
list[i] = 1.0;
}
}
//
// Typed variable setters.
//
void doSetInt8Var(Int8List list) {
for (int i = 0; i < list.length; i++) {
list[i] = i;
}
}
void doSetUint8Var(Uint8List list) {
for (int i = 0; i < list.length; i++) {
list[i] = i;
}
}
void doSetUint8ClampedVar(Uint8ClampedList list) {
for (int i = 0; i < list.length; i++) {
list[i] = i;
}
}
void doSetInt16Var(Int16List list) {
for (int i = 0; i < list.length; i++) {
list[i] = i;
}
}
void doSetUint16Var(Uint16List list) {
for (int i = 0; i < list.length; i++) {
list[i] = i;
}
}
void doSetInt32Var(Int32List list) {
for (int i = 0; i < list.length; i++) {
list[i] = i;
}
}
void doSetUint32Var(Uint32List list) {
for (int i = 0; i < list.length; i++) {
list[i] = i;
}
}
void doSetInt64Var(Int64List list) {
for (int i = 0; i < list.length; i++) {
list[i] = i;
}
}
void doSetUint64Var(Uint64List list) {
for (int i = 0; i < list.length; i++) {
list[i] = i;
}
}
void doSetFloat32Var(Float32List list) {
double x = 0.0;
for (int i = 0; i < list.length; i++) {
list[i] = x++;
}
}
void doSetFloat64Var(Float64List list) {
double x = 0.0;
for (int i = 0; i < list.length; i++) {
list[i] = x++;
}
}
//
// Typed getters.
//
int doGetInt8(Int8List list) {
int x = 0;
for (int i = 0; i < list.length; i++) {
x += list[i];
}
return x;
}
int doGetUint8(Uint8List list) {
int x = 0;
for (int i = 0; i < list.length; i++) {
x += list[i];
}
return x;
}
int doGetUint8Clamped(Uint8ClampedList list) {
int x = 0;
for (int i = 0; i < list.length; i++) {
x += list[i];
}
return x;
}
int doGetInt16(Int16List list) {
int x = 0;
for (int i = 0; i < list.length; i++) {
x += list[i];
}
return x;
}
int doGetUint16(Uint16List list) {
int x = 0;
for (int i = 0; i < list.length; i++) {
x += list[i];
}
return x;
}
int doGetInt32(Int32List list) {
int x = 0;
for (int i = 0; i < list.length; i++) {
x += list[i];
}
return x;
}
int doGetUint32(Uint32List list) {
int x = 0;
for (int i = 0; i < list.length; i++) {
x += list[i];
}
return x;
}
int doGetInt64(Int64List list) {
int x = 0;
for (int i = 0; i < list.length; i++) {
x += list[i];
}
return x;
}
int doGetUint64(Uint64List list) {
int x = 0;
for (int i = 0; i < list.length; i++) {
x += list[i];
}
return x;
}
double doGetFloat32(Float32List list) {
double x = 0.0;
for (int i = 0; i < list.length; i++) {
x += list[i];
}
return x;
}
double doGetFloat64(Float64List list) {
double x = 0.0;
for (int i = 0; i < list.length; i++) {
x += list[i];
}
return x;
}
//
// Benchmark fixtures.
//
const N = 1000;
class Int8ListBench extends BenchmarkBase {
var list = Int8List(N);
Int8ListBench() : super('TypedData.Int8ListBench');
@override
void run() {
doSetInt8(list);
final int x = doGetInt8(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint8ListBench extends BenchmarkBase {
var list = Uint8List(N);
Uint8ListBench() : super('TypedData.Uint8ListBench');
@override
void run() {
doSetUint8(list);
final int x = doGetUint8(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint8ClampedListBench extends BenchmarkBase {
var list = Uint8ClampedList(N);
Uint8ClampedListBench() : super('TypedData.Uint8ClampedListBench');
@override
void run() {
doSetUint8Clamped(list);
final int x = doGetUint8Clamped(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int16ListBench extends BenchmarkBase {
var list = Int16List(N);
Int16ListBench() : super('TypedData.Int16ListBench');
@override
void run() {
doSetInt16(list);
final int x = doGetInt16(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint16ListBench extends BenchmarkBase {
var list = Uint16List(N);
Uint16ListBench() : super('TypedData.Uint16ListBench');
@override
void run() {
doSetUint16(list);
final int x = doGetUint16(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int32ListBench extends BenchmarkBase {
var list = Int32List(N);
Int32ListBench() : super('TypedData.Int32ListBench');
@override
void run() {
doSetInt32(list);
final int x = doGetInt32(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint32ListBench extends BenchmarkBase {
var list = Uint32List(N);
Uint32ListBench() : super('TypedData.Uint32ListBench');
@override
void run() {
doSetUint32(list);
final int x = doGetUint32(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int64ListBench extends BenchmarkBase {
var list = Int64List(N);
Int64ListBench() : super('TypedData.Int64ListBench');
@override
void run() {
doSetInt64(list);
final int x = doGetInt64(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint64ListBench extends BenchmarkBase {
var list = Uint64List(N);
Uint64ListBench() : super('TypedData.Uint64ListBench');
@override
void run() {
doSetUint64(list);
final int x = doGetUint64(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Float32ListBench extends BenchmarkBase {
var list = Float32List(N);
Float32ListBench() : super('TypedData.Float32ListBench');
@override
void run() {
doSetFloat32(list);
final double x = doGetFloat32(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Float64ListBench extends BenchmarkBase {
var list = Float64List(N);
Float64ListBench() : super('TypedData.Float64ListBench');
@override
void run() {
doSetFloat64(list);
final double x = doGetFloat64(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int8ListViewBench extends BenchmarkBase {
var list = Int8List.view(Int8List(N).buffer);
Int8ListViewBench() : super('TypedData.Int8ListViewBench');
@override
void run() {
doSetInt8(list);
final int x = doGetInt8(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint8ListViewBench extends BenchmarkBase {
var list = Uint8List.view(Uint8List(N).buffer);
Uint8ListViewBench() : super('TypedData.Uint8ListViewBench');
@override
void run() {
doSetUint8(list);
final int x = doGetUint8(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint8ClampedListViewBench extends BenchmarkBase {
var list = Uint8ClampedList.view(Uint8ClampedList(N).buffer);
Uint8ClampedListViewBench() : super('TypedData.Uint8ClampedListViewBench');
@override
void run() {
doSetUint8Clamped(list);
final int x = doGetUint8Clamped(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int16ListViewBench extends BenchmarkBase {
var list = Int16List.view(Int16List(N).buffer);
Int16ListViewBench() : super('TypedData.Int16ListViewBench');
@override
void run() {
doSetInt16(list);
final int x = doGetInt16(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint16ListViewBench extends BenchmarkBase {
var list = Uint16List.view(Uint16List(N).buffer);
Uint16ListViewBench() : super('TypedData.Uint16ListViewBench');
@override
void run() {
doSetUint16(list);
final int x = doGetUint16(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int32ListViewBench extends BenchmarkBase {
var list = Int32List.view(Int32List(N).buffer);
Int32ListViewBench() : super('TypedData.Int32ListViewBench');
@override
void run() {
doSetInt32(list);
final int x = doGetInt32(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint32ListViewBench extends BenchmarkBase {
var list = Uint32List.view(Uint32List(N).buffer);
Uint32ListViewBench() : super('TypedData.Uint32ListViewBench');
@override
void run() {
doSetUint32(list);
final int x = doGetUint32(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int64ListViewBench extends BenchmarkBase {
var list = Int64List.view(Int64List(N).buffer);
Int64ListViewBench() : super('TypedData.Int64ListViewBench');
@override
void run() {
doSetInt64(list);
final int x = doGetInt64(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint64ListViewBench extends BenchmarkBase {
var list = Uint64List.view(Uint64List(N).buffer);
Uint64ListViewBench() : super('TypedData.Uint64ListViewBench');
@override
void run() {
doSetUint64(list);
final int x = doGetUint64(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Float32ListViewBench extends BenchmarkBase {
var list = Float32List.view(Float32List(N).buffer);
Float32ListViewBench() : super('TypedData.Float32ListViewBench');
@override
void run() {
doSetFloat32(list);
final double x = doGetFloat32(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Float64ListViewBench extends BenchmarkBase {
var list = Float64List.view(Float64List(N).buffer);
Float64ListViewBench() : super('TypedData.Float64ListViewBench');
@override
void run() {
doSetFloat64(list);
final double x = doGetFloat64(list);
if (x != N) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int8ListVarBench extends BenchmarkBase {
var list = Int8List(N);
Int8ListVarBench() : super('TypedData.Int8ListVarBench');
@override
void run() {
doSetInt8Var(list);
final int x = doGetInt8(list);
if (x != -212) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint8ListVarBench extends BenchmarkBase {
var list = Uint8List(N);
Uint8ListVarBench() : super('TypedData.Uint8ListVarBench');
@override
void run() {
doSetUint8Var(list);
final int x = doGetUint8(list);
if (x != 124716) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint8ClampedListVarBench extends BenchmarkBase {
var list = Uint8ClampedList(N);
Uint8ClampedListVarBench() : super('TypedData.Uint8ClampedListVarBench');
@override
void run() {
doSetUint8ClampedVar(list);
final int x = doGetUint8Clamped(list);
if (x != 222360) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int16ListVarBench extends BenchmarkBase {
var list = Int16List(N);
Int16ListVarBench() : super('TypedData.Int16ListVarBench');
@override
void run() {
doSetInt16Var(list);
final int x = doGetInt16(list);
if (x != 499500) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint16ListVarBench extends BenchmarkBase {
var list = Uint16List(N);
Uint16ListVarBench() : super('TypedData.Uint16ListVarBench');
@override
void run() {
doSetUint16Var(list);
final int x = doGetUint16(list);
if (x != 499500) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int32ListVarBench extends BenchmarkBase {
var list = Int32List(N);
Int32ListVarBench() : super('TypedData.Int32ListVarBench');
@override
void run() {
doSetInt32Var(list);
final int x = doGetInt32(list);
if (x != 499500) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint32ListVarBench extends BenchmarkBase {
var list = Uint32List(N);
Uint32ListVarBench() : super('TypedData.Uint32ListVarBench');
@override
void run() {
doSetUint32Var(list);
final int x = doGetUint32(list);
if (x != 499500) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int64ListVarBench extends BenchmarkBase {
var list = Int64List(N);
Int64ListVarBench() : super('TypedData.Int64ListVarBench');
@override
void run() {
doSetInt64Var(list);
final int x = doGetInt64(list);
if (x != 499500) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint64ListVarBench extends BenchmarkBase {
var list = Uint64List(N);
Uint64ListVarBench() : super('TypedData.Uint64ListVarBench');
@override
void run() {
doSetUint64Var(list);
final int x = doGetUint64(list);
if (x != 499500) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Float32ListVarBench extends BenchmarkBase {
var list = Float32List(N);
Float32ListVarBench() : super('TypedData.Float32ListVarBench');
@override
void run() {
doSetFloat32Var(list);
final double x = doGetFloat32(list);
if (x != 499500.0) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Float64ListVarBench extends BenchmarkBase {
var list = Float64List(N);
Float64ListVarBench() : super('TypedData.Float64ListVarBench');
@override
void run() {
doSetFloat64Var(list);
final double x = doGetFloat64(list);
if (x != 499500.0) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int8ListViewVarBench extends BenchmarkBase {
var list = Int8List.view(Int8List(N).buffer);
Int8ListViewVarBench() : super('TypedData.Int8ListViewVarBench');
@override
void run() {
doSetInt8Var(list);
final int x = doGetInt8(list);
if (x != -212) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint8ListViewVarBench extends BenchmarkBase {
var list = Uint8List.view(Uint8List(N).buffer);
Uint8ListViewVarBench() : super('TypedData.Uint8ListViewVarBench');
@override
void run() {
doSetUint8Var(list);
final int x = doGetUint8(list);
if (x != 124716) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint8ClampedListViewVarBench extends BenchmarkBase {
var list = Uint8ClampedList.view(Uint8ClampedList(N).buffer);
Uint8ClampedListViewVarBench()
: super('TypedData.Uint8ClampedListViewVarBench');
@override
void run() {
doSetUint8ClampedVar(list);
final int x = doGetUint8Clamped(list);
if (x != 222360) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int16ListViewVarBench extends BenchmarkBase {
var list = Int16List.view(Int16List(N).buffer);
Int16ListViewVarBench() : super('TypedData.Int16ListViewVarBench');
@override
void run() {
doSetInt16Var(list);
final int x = doGetInt16(list);
if (x != 499500) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint16ListViewVarBench extends BenchmarkBase {
var list = Uint16List.view(Uint16List(N).buffer);
Uint16ListViewVarBench() : super('TypedData.Uint16ListViewVarBench');
@override
void run() {
doSetUint16Var(list);
final int x = doGetUint16(list);
if (x != 499500) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int32ListViewVarBench extends BenchmarkBase {
var list = Int32List.view(Int32List(N).buffer);
Int32ListViewVarBench() : super('TypedData.Int32ListViewVarBench');
@override
void run() {
doSetInt32Var(list);
final int x = doGetInt32(list);
if (x != 499500) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint32ListViewVarBench extends BenchmarkBase {
var list = Uint32List.view(Uint32List(N).buffer);
Uint32ListViewVarBench() : super('TypedData.Uint32ListViewVarBench');
@override
void run() {
doSetUint32Var(list);
final int x = doGetUint32(list);
if (x != 499500) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Int64ListViewVarBench extends BenchmarkBase {
var list = Int64List.view(Int64List(N).buffer);
Int64ListViewVarBench() : super('TypedData.Int64ListViewVarBench');
@override
void run() {
doSetInt64Var(list);
final int x = doGetInt64(list);
if (x != 499500) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Uint64ListViewVarBench extends BenchmarkBase {
var list = Uint64List.view(Uint64List(N).buffer);
Uint64ListViewVarBench() : super('TypedData.Uint64ListViewVarBench');
@override
void run() {
doSetUint64Var(list);
final int x = doGetUint64(list);
if (x != 499500) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Float32ListViewVarBench extends BenchmarkBase {
var list = Float32List.view(Float32List(N).buffer);
Float32ListViewVarBench() : super('TypedData.Float32ListViewVarBench');
@override
void run() {
doSetFloat32Var(list);
final double x = doGetFloat32(list);
if (x != 499500.0) {
throw Exception('$name: Unexpected result: $x');
}
}
}
class Float64ListViewVarBench extends BenchmarkBase {
var list = Float64List.view(Float64List(N).buffer);
Float64ListViewVarBench() : super('TypedData.Float64ListViewVarBench');
@override
void run() {
doSetFloat64Var(list);
final double x = doGetFloat64(list);
if (x != 499500.0) {
throw Exception('$name: Unexpected result: $x');
}
}
}
//
// Main driver.
//
void main() {
final microBenchmarks = [
() => Int8ListBench(),
() => Uint8ListBench(),
() => Uint8ClampedListBench(),
() => Int16ListBench(),
() => Uint16ListBench(),
() => Int32ListBench(),
() => Uint32ListBench(),
() => Int64ListBench(),
() => Uint64ListBench(),
() => Float32ListBench(),
() => Float64ListBench(),
() => Int8ListViewBench(),
() => Uint8ListViewBench(),
() => Uint8ClampedListViewBench(),
() => Int16ListViewBench(),
() => Uint16ListViewBench(),
() => Int32ListViewBench(),
() => Uint32ListViewBench(),
() => Int64ListViewBench(),
() => Uint64ListViewBench(),
() => Float32ListViewBench(),
() => Float64ListViewBench(),
() => Int8ListVarBench(),
() => Uint8ListVarBench(),
() => Uint8ClampedListVarBench(),
() => Int16ListVarBench(),
() => Uint16ListVarBench(),
() => Int32ListVarBench(),
() => Uint32ListVarBench(),
() => Int64ListVarBench(),
() => Uint64ListVarBench(),
() => Float32ListVarBench(),
() => Float64ListVarBench(),
() => Int8ListViewVarBench(),
() => Uint8ListViewVarBench(),
() => Uint8ClampedListViewVarBench(),
() => Int16ListViewVarBench(),
() => Uint16ListViewVarBench(),
() => Int32ListViewVarBench(),
() => Uint32ListViewVarBench(),
() => Int64ListViewVarBench(),
() => Uint64ListViewVarBench(),
() => Float32ListViewVarBench(),
() => Float64ListViewVarBench(),
];
for (var mbm in microBenchmarks) {
mbm().report();
}
}
@@ -1,29 +0,0 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'TypedDataCopyLib.dart';
void main() {
final benchmarks = [
() => Int8ViewToInt8View(),
() => Int8ToInt8(),
() => Int8ToUint8Clamped(),
() => Int8ViewToInt8(),
() => ByteSwap(),
];
// Run all the code to ensure consistent polymorphism in shared code.
for (var bm in benchmarks) {
bm()
..setup()
..run()
..run();
}
for (var bm in benchmarks) {
bm().report();
}
}
@@ -1,176 +0,0 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
// Typed data block copy benchmark.
const int size = 256 * 1024;
class Int8ViewToInt8View extends BenchmarkBase {
Int8ViewToInt8View() : super('TypedDataCopy.Int8ViewToInt8View');
var a1;
var a2;
@override
void setup() {
final storage = Int8List(size);
final buffer = storage.buffer;
a1 = Int8List.view(buffer, 0, buffer.lengthInBytes);
a2 = Int8List.view(buffer, 8, buffer.lengthInBytes - 8);
for (int i = 0; i < a1.length; i++) {
a1[i] = i;
}
}
@override
void run() {
// Shift all bytes 8 positions nearer to the front.
a1.setRange(0, a2.length, a2);
final check = a1[a1.length - 8 - 1];
if (check != -1) throw 'Bad $check';
}
}
class Int8ViewToInt8 extends BenchmarkBase {
Int8ViewToInt8() : super('TypedDataCopy.Int8ViewToInt8');
var a1;
var a2;
@override
void setup() {
a1 = Int8List(size);
final buffer = a1.buffer;
a2 = Int8List.view(buffer, 8, buffer.lengthInBytes - 8);
for (int i = 0; i < a1.length; i++) {
a1[i] = i;
}
}
@override
void run() {
// Shift all bytes 8 positions nearer to the front.
a1.setRange(0, a2.length, a2);
final check = a1[a1.length - 8 - 1];
if (check != -1) {
throw 'Bad $check';
}
}
}
class Int8ToInt8 extends BenchmarkBase {
Int8ToInt8() : super('TypedDataCopy.Int8ToInt8');
var a1;
@override
void setup() {
a1 = Int8List(size);
for (int i = 0; i < a1.length; i++) {
a1[i] = i;
}
}
@override
void run() {
// Shift all bytes 8 positions nearer to the front.
a1.setRange(0, a1.length - 8, a1, 8);
final check = a1[a1.length - 8 - 1];
if (check != -1) {
throw 'Bad $check';
}
}
}
class Int8ToUint8Clamped extends BenchmarkBase {
Int8ToUint8Clamped() : super('TypedDataCopy.Int8ToUint8Clamped');
var a1;
var a2;
@override
void setup() {
a1 = Uint8ClampedList(size);
a2 = Int8List(size);
for (int i = 0; i < a2.length; i++) {
a2[i] = i;
}
}
@override
void run() {
a1.setRange(0, a2.length, a2, 0);
var check = a1[100];
if (check != 100) {
throw 'Bad $check';
}
check = a1[200];
if (check != 0) {
throw 'Bad $check';
}
}
}
class ByteSwap extends BenchmarkBase {
ByteSwap() : super('TypedDataCopy.ByteSwap');
final a8 = Int8List(size ~/ 16);
@override
void setup() {
for (int i = 0; i < a8.length; i++) {
a8[i] = i;
}
}
void check(e0, e1, e2, e3) {
final a0 = a8[0];
final a1 = a8[1];
final a2 = a8[2];
final a3 = a8[3];
if (a0 != e0 || a1 != e1 || a2 != e2 || a3 != e3) {
throw 'Bad: $a0 $a1 $a2 $a3, expected $e0 $e1 $e2 $e3';
}
}
@override
void run() {
final b = ByteData.view(a8.buffer);
// Do several passes over the data, reading and writing in different widths
// with different endianes.
for (int i = 0; i < b.lengthInBytes; i += 4) {
final e = b.getInt32(i); // Implicit big endian.
b.setInt32(i, e, Endian.little);
}
check(3, 2, 1, 0);
for (int i = 0; i < b.lengthInBytes; i += 2) {
final e = b.getInt16(i, Endian.big);
b.setInt16(i, e, Endian.little);
}
check(2, 3, 0, 1);
for (int i = 0; i < b.lengthInBytes; i += 4) {
final e = b.getUint32(i, Endian.little);
b.setUint32(i, e); // Implicit big endian.
}
check(1, 0, 3, 2);
for (int i = 0; i < b.lengthInBytes; i += 2) {
final e = b.getUint16(i, Endian.little);
b.setUint16(i, e, Endian.big);
}
check(0, 1, 2, 3); // Back to normal for the next run().
}
}
@@ -1,126 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Micro-benchmarks for copying typed data lists.
// @dart=2.9
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
abstract class Uint8ListCopyBenchmark extends BenchmarkBase {
final int size;
Uint8List input;
Uint8List result;
Uint8ListCopyBenchmark(String method, this.size)
: super('TypedDataDuplicate.Uint8List.$size.$method');
@override
void setup() {
input = Uint8List(size);
for (var i = 0; i < size; ++i) {
input[i] = (i + 3) & 0xff;
}
}
@override
void teardown() {
for (var i = 0; i < size; ++i) {
if (result[i] != ((i + 3) & 0xff)) {
throw 'Unexpected result';
}
}
}
}
class Uint8ListCopyViaFromListBenchmark extends Uint8ListCopyBenchmark {
Uint8ListCopyViaFromListBenchmark(int size) : super('fromList', size);
@override
void run() {
result = Uint8List.fromList(input);
}
}
class Uint8ListCopyViaLoopBenchmark extends Uint8ListCopyBenchmark {
Uint8ListCopyViaLoopBenchmark(int size) : super('loop', size);
@override
void run() {
final input = this.input;
final result = Uint8List(input.length);
for (var i = 0; i < input.length; i++) {
result[i] = input[i];
}
this.result = result;
}
}
abstract class Float64ListCopyBenchmark extends BenchmarkBase {
final int size;
Float64List input;
Float64List result;
Float64ListCopyBenchmark(String method, this.size)
: super('TypedDataDuplicate.Float64List.$size.$method');
@override
void setup() {
input = Float64List(size);
for (var i = 0; i < size; ++i) {
input[i] = (i - 7).toDouble();
}
}
@override
void teardown() {
for (var i = 0; i < size; ++i) {
if (result[i] != (i - 7).toDouble()) {
throw 'Unexpected result';
}
}
}
}
class Float64ListCopyViaFromListBenchmark extends Float64ListCopyBenchmark {
Float64ListCopyViaFromListBenchmark(int size) : super('fromList', size);
@override
void run() {
result = Float64List.fromList(input);
}
}
class Float64ListCopyViaLoopBenchmark extends Float64ListCopyBenchmark {
Float64ListCopyViaLoopBenchmark(int size) : super('loop', size);
@override
void run() {
final input = this.input;
final result = Float64List(input.length);
for (var i = 0; i < input.length; i++) {
result[i] = input[i];
}
this.result = result;
}
}
void main() {
final sizes = [8, 32, 256, 16384];
final benchmarks = [
for (int size in sizes) ...[
Uint8ListCopyViaLoopBenchmark(size),
Uint8ListCopyViaFromListBenchmark(size),
],
for (int size in sizes) ...[
Float64ListCopyViaLoopBenchmark(size),
Float64ListCopyViaFromListBenchmark(size),
],
];
for (var bench in benchmarks) {
bench.report();
}
}
-130
View File
@@ -1,130 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
// Benchmark for UTF-8 decoding
// @dart=2.9
import 'dart:convert';
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'datext_latin1_10k.dart';
import 'entext_ascii_10k.dart';
import 'netext_3_10k.dart';
import 'rutext_2_10k.dart';
import 'sktext_10k.dart';
import 'zhtext_10k.dart';
class Utf8Decode extends BenchmarkBase {
final String language;
final String text;
final int size;
final bool allowMalformed;
List<Uint8List> chunks;
int totalInputSize;
int totalOutputSize;
static String _makeName(String language, int size, bool allowMalformed) {
String name = 'Utf8Decode.$language.';
name +=
size >= 1000000
? '${size ~/ 1000000}M'
: size >= 1000
? '${size ~/ 1000}k'
: '$size';
if (allowMalformed) name += '.malformed';
return name;
}
Utf8Decode(this.language, this.text, this.size, this.allowMalformed)
: super(_makeName(language, size, allowMalformed));
@override
void setup() {
final Uint8List data = utf8.encode(text);
if (data.length != 10000) {
throw 'Expected input data of exactly 10000 bytes.';
}
if (size < data.length) {
// Split into chunks.
chunks = <Uint8List>[];
int startPos = 0;
for (int pos = size; pos < data.length; pos += size) {
int endPos = pos;
while ((data[endPos] & 0xc0) == 0x80) {
endPos--;
}
chunks.add(Uint8List.fromList(data.sublist(startPos, endPos)));
startPos = endPos;
}
chunks.add(Uint8List.fromList(data.sublist(startPos, data.length)));
totalInputSize = data.length;
totalOutputSize = text.length;
} else if (size > data.length) {
// Repeat data to the desired length.
final Uint8List expanded = Uint8List(size);
for (int i = 0; i < size; i++) {
expanded[i] = data[i % data.length];
}
chunks = <Uint8List>[expanded];
totalInputSize = size;
totalOutputSize = text.length * size ~/ data.length;
} else {
// Use data as is.
chunks = <Uint8List>[data];
totalInputSize = data.length;
totalOutputSize = text.length;
}
}
@override
void run() {
int lengthSum = 0;
for (int i = 0; i < chunks.length; i++) {
final String s = utf8.decode(chunks[i], allowMalformed: allowMalformed);
lengthSum += s.length;
}
if (lengthSum != totalOutputSize) {
throw 'Output length doesn\'t match expected.';
}
}
@override
void exercise() {
// Only a single run per measurement.
run();
}
@override
double measure() {
// Report time per input byte.
return super.measure() / totalInputSize;
}
@override
void report() {
// Report time in nanoseconds.
final double score = measure() * 1000.0;
print('$name(RunTime): $score ns.');
}
}
void main(List<String> args) {
const texts = {'en': en, 'da': da, 'sk': sk, 'ru': ru, 'ne': ne, 'zh': zh};
final bool testMalformed =
args != null && args.isNotEmpty && args.first == 'malformed';
final benchmarks = [
// Only benchmark with allowMalformed: false unless specified otherwise.
for (bool allowMalformed in [false, if (testMalformed) true])
for (int size in [10, 10000, 10000000])
for (String language in texts.keys)
() => Utf8Decode(language, texts[language], size, allowMalformed),
];
for (var bm in benchmarks) {
bm().report();
}
}
@@ -1,64 +0,0 @@
// This text is an extract from the Danish Wikipedia article about Donald Duck
// (Anders And): https://da.wikipedia.org/wiki/Anders_And
//
// The extract is based on the Wikipedia database dump. All markup has been
// removed using WikiExtractor: https://github.com/attardi/wikiextractor
//
// The material is licensed under the Creative Commons Attribution-Share-Alike
// License 3.0: https://creativecommons.org/licenses/by-sa/3.0/
// @dart=2.9
const String da = '''
Anders And
Anders Fauntleroy And er en berømt figur i Disneys tegnefilm og tegneserier. Selv om han ikke er særligt populær i USA, optræder han i mange ugeblade i Europa: I Norge, Tyskland, Sverige, Danmark, Holland, Italien med flere. Hans første optræden var i tegnefilmen "The Wise Little Hen" (Den kloge lille høne) fra 9. juni 1934. Hans karakteristiske stemme blev indtalt af radiokomikeren Clarence Nash, der siden fast lagde stemme til.
Efter Nash' død i 1985 overtog tegnefilmsdubberen Tony Anselmo. Det var i øvrigt Nash selv, der trænede Anselmo til at lyde som Anders And. I Danmark har tre lagt stemme til Anders And: Bjarne H. Hansen, Dick Kaysø og Peter Zhelder. Dick Kaysø og Peter Zhelder lægger stadigvæk stemme til ham.
Anders And var en bifigur til filmen Den lille kloge Høne, han havde et langt spidst næb og en utrolig kort lunte; der skulle ikke meget til for at udløse et raserianfald hos ham. Klassikerne er fra 1930'erne, hvor Mickey, Fedtmule og Anders er et trekløver, der er film som "Mickeys Campingvogn," "Tårnuret" og "Ensomme Spøgelser." Fred Spencer og Dick Lundy var animatorer. Efterhånden opnåede anden større popularitet, hvad der ikke rigtig huede Disney, der ikke brød sig om den krakilske and. Men Anders blev forfremmet til hovedfigur i en serie film, der begyndte med "Anders And og Strudsen" i 1938. Med den var det "ande-teamet" hos Disney født: instruktøren Jack King og assistenterne Carl Barks (den senere serieskaber), Chuck Couch, Harry Reeves og Jack Hannah. Han var stadigvæk en hidsigprop, men han blev gjort mere nuanceret, og nye figurer blev tilføjet som nevøerne Rip, Rap og Rup, kæresten Andersine And og i en enkelt film Fætter Guf.
Under 2. verdenskrig blev der lavet film om anden i militærtjeneste, som han selvfølgelig gør meget klodset. Mest kendt er "Der Fuehrers Face" fra 1943, hvor anden drømmer, at han er i diktaturstaten Nutziland. Den film blev arkiveret af Disney efter krigen, men er senere vist meget uofficielt. Desuden medvirkede han i to mindre kendte spillefilm "Saludos Amigos" 1943 og "The Three Caballeros" 1945, der gav et lystigt billede af livet i Latinamerika.
Efter krigen blev omgivelserne mere hjemlige, men næppe mere fredfyldte. I 1947 overtog Jack Hannah pladsen som instruktør. Filmene handlede ofte om klammeri med andre, det kunne være en bi, Chip og Chap eller bare ting han ikke kunne til at makke ret. Anders var her ofte plageånden, hvis egne drillerier kom tilbage som en boomerang.
Fjernsynets fremmarch i 1950'erne satte snart stopper for de korte tegnefilm, og Jack Hannah blev sat til at redigere Disneys tv-shows og kæde de korte tegnefilm sammen i et længere forløb. Her blev Anders gjort mere sympatisk, men det var eksperten i alt, Raptus von And, der gjorde mest for tv-showet. I et andet tv-show Disney Sjov medvirkede Anders i tv-serierne Rip, Rap og Rup på eventyr, Bonkers, og Rap Sjak. I Rip, Rap og Rup på eventyr, var han sjældent med, men fik et nyt tøj. I Rap Sjak var hans matrostøj skiftet ud med en hawaii-skjorte med røde og hvide blomster. I Bonkers var han også med kort tid.
Anders And gik til tegneserien allerede tidligt efter sin debut i 1934, hvor han i avisstriber optrådte med sin makker fra "The Wise Little Hen," Peter Gris. Fra den 10. februar 1935 blev han en del af Mickeys avisstribe som musens kujonagtige og drillesyge ven, men fra 1936 kaprede han hovedrollen i Silly Symphony-striben. Forfatteren Ted Osborne og tegneren Al Taliaferro, der stod bag serieudgaven af The Wise Little Hen, pressede , og da det blev en succes kunne forfatteren Bob Karp i samarbejde med Taliaferro lave andens egen avisstribe.
Det blev en populær serie. I de allertidligste serier var Anders en hidsig, ondskabsfuld og pueril and med langt spidst næb og hænder, der knap kunne skelnes fra vinger. Senere blev han mere voksen, da han fik ansvaret for sine tre nevøer Rip, Rap og Rup, og kæresten Andersine kom til sammen med Bedstemor And.
Tegneseriefiguren Anders And blev senere udviklet yderligere af Carl Barks. I de tidlige tegnefilm var han for det meste doven og hidsig; men for at gøre hans figur brugbar til en tegneserie besluttede Barks at udvide hans personlighed. Anders' mest gennemgående karaktertræk er hans notoriske uheld, som desuden har den narrative funktion at give adgang til spændende eventyr, uden at serien udvikler sig for meget. På denne måde kan Anders eksempelvis blive involveret i alverdens skattejagter, og da han altid ender med at miste den fundne gevinst, kan alle historierne starte fra samme udgangspunkt.
For at give Anders en verden at bo i, skabte Barks byen Andeby i den amerikanske stat Calisota (som er en blanding af de to amerikanske stater Californien og Minnesota) med indbyggere som den rige onkel Joakim von And, den heldige Fætter Højben og den dygtige opfinder Georg Gearløs.
Anders lægger med sit engelske navn Donald Duck i øvrigt navn til donaldismen, fankulturen omkring Disney-tegneserier og -tegnefilm, som den norske forfatter Jon Gisle udviklede med sin bog af samme navn.
Anders bor i Andeby Paradisæblevej 111 med sine tre nevøer Rip, Rap og Rup. De er stort set identiske, men de kan i nogle historier identificeres , hvilken farve kasket de har .
Ifølge Disneytegneserieforfatteren Don Rosa var Anders født et eller andet sted omkring 1920 men dette er "ikke" officielt. Ifølge Carl Barks' stamtræ (senere udviklet og genbygget af Don Rosa for den danske udgiver Egmont Serieforlaget) er Anders' forældre Hortensia von And og Rapmus And. Anders har en søster ved navn Della And, men hverken hun eller Anders' forældre optræder i tegnefilmene eller tegneserierne bortset fra særlige steder som eksempelvis i Her er dit liv, Joakim. Ifølge Don Rosa er Anders og Della tvillinger.
Fra tegnefilmen "Mr. Duck Steps Out" har Anders' kæreste været Andersine And, men han går i stadig fare for at miste hende til den heldige Fætter Højben. I nogle italienske historier er Anders også superhelt under dæknavnet "Stålanden".
Anders' onkel, Joakim von And, er den rigeste and i verden.
Sammen med onkelen og nevøerne Rip, Rap og Rup har Anders And rejst jorden rundt til mange forskellige lande og steder. Blandt disse er landet Langtbortistan, hvis navn blev opfundet af den danske oversætter Sonja Rindom og senere er gledet ind i almindeligt, dansk sprogbrug.
I de tidlige historier af Carl Barks havde Anders en hale, der stak langt bagud. Han havde langt næb og lang hals, og hans matrostrøje havde fire knapper. Hans lange hals passede godt til egenskaben nysgerrighed og det lange næb til hans hidsighed, hvilket var to egenskaber, der prægede ham mest. Disse tidlige historier var også præget af en grov komik i stil med tegnefilmene.
Siden fik han et mere strømlinet udseende og kortere næb (dog ikke kort som visse tegnere i 1960'erne gjorde det!) og kun to knapper på trøjen, et udseende de øvrige andetegnere også tager til sig. Her blev hans natur også mere sammensat, og han ligner mest af alt en tragisk helt. Komikken kommer mere og mere til at ligge i replikkerne.
Anders And optræder særligt i jumbobøgerne med en hemmelig identitet i form af superhelten Stålanden. Figuren er inspireret af Batman og er skabt af den italienske forfatter Guido Martina i samarbejde med kunstneren Giovan Battista Carpi i 1969 i hans italienske navn Paperinik. Ofte tegnet af Romano Scarpa.
I lighed med inspirationskilden er han maskeret og har et hav af tekniske opfindelser, som han bruger i kamp mod forbryderne og overvejende! i kamp for at redde sit andet jeg, Anders And, ud af kniben. Den eneste, som kender hans hemmelige identitet, er opfinderen Georg Gearløs, som har udstyret gamle 313 med moderne udstyr og finurligheder. Det er ikke tit at Stålanden optræder; næsten kun i Jumbobøger, men har dog også optrådt i Anders And-bladene med en gæstehistorie, hvor Stålanden kæmper mod en tidligere fjende, som nu havde kaldt sig Lord Hvalros.
Efter at Stålanden i starten af 1990'erne ikke var benyttet så meget af historieskriverne, forsvandt han næsten ud af Disney-universet indtil 1996, hvor en ny serie, "Stålanden på nye eventyr", startede med Stålanden i hovedrollen (umiddelbart inspireret af Marvel universet). Denne relancering af Stålanden gav karakteren det ekstra, der skulle til for at få et godt comeback.
I modsætning til størstedelen af Anders And-tegneserier har denne serie en sammenhængende forløb. I serien optræder kun sjældent de andre figurer fra de normale Anders And tegneserier; oftest er det kun en kort birolle eller en reference, men til gengæld er en mængde nye figurer kommet til.
Serien starter med, at Anders And er ansat som vicevært i Ducklair Tower, et højhus bygget af mangemilliardæren Everett Ducklair, en fremragende videnskabsmand og opfinder, som forlod Andeby og drog til et tibetansk kloster, Dhasam-Bul. Anders finder Globus, en kunstig intelligens skabt af Ducklair, samt Ducklair's arsenal af våben og opfindelser. Dette bliver starten på Anders' liv som Stålanden.
En mængde temaer var ofte i centrum for historierne, bl.a. tidsrejser og Tidspolitiets kamp med tidspiraterne fra Organisationen, invasion fra rummet af de magtsyge evronianere, Stålandens samarbejde med FBI og meget mere.
Serien fik en fornyelse i 2001, hvilket ændrede markant historierne. Everett Ducklair vender tilbage, slukker Globus, smider Stålanden ud af Ducklair Tower og genopretter sit gamle imperium. Undervejs bliver Ducklair's to døtre afsløret. De hader begge Everett af grunde, der ikke bliver afsløret til fulde, selvom det bliver antydet, at Everett skilte sig af med deres mor på en eller anden måde.
Denne fornyelse holdt 18 numre, før serien blev afsluttet, dog uden at historierne fik en slutning.
Barks-historien "Anders And og den gyldne hjelm" fra 1954 kom i 2006 med i ''';
@@ -1,37 +0,0 @@
// This text is an extract from the English Wikipedia article about Anarchism:
// https://en.wikipedia.org/wiki/Anarchism
//
// The extract is based on the Wikipedia database dump. All markup has been
// removed using WikiExtractor: https://github.com/attardi/wikiextractor
//
// The material is licensed under the Creative Commons Attribution-Share-Alike
// License 3.0: https://creativecommons.org/licenses/by-sa/3.0/
// @dart=2.9
const String en = '''
Anarchism
Anarchism is a radical political movement that is highly skeptical towards authority and rejects all forms of unjust hierarchy. It calls for the abolition of the state which it holds to be undesirable, unnecessary, and harmful. Anarchism advocates for the replacement of the state with stateless societies or other forms of free associations.
Anarchism's timeline stretches back to prehistory when people lived in anarchistic societies long before the establishment of formal states, kingdoms or empires. With the rise of organised hierarchical bodies, skepticism towards authority also rose, but it was not until the 19th century a self-conscious political movement was formed. During the latest half of 19th and the first decades of 20th century, the anarchist movement flourished to most parts of the world, and had a significant role in worker's struggles for emancipation. Various branches of anarchism were espoused during those times. Anarchists took part in several revolutions, most notably in the Spanish Civil War, where they were crushed by the fascists forces in 1939, marking the end of the classical era of anarchism. In the latest decades of the 20th century, the anarchist movement nonetheless became relevant and vivid once more.
Anarchism employ various tactics in order to meet their ideal ends; these can be broadly separated in revolutionary and evolutionary tactics. There is significant overlap between the two legs which are merely descriptive. Revolutionary tactics aim to bring down authority and state, and have taken a violent turn in the past. Evolutionary tactics aim to prefigure what an anarchist society would be like. Anarchism's thought, criticism and praxis has played a part in diverse fields of human society.
The etymological origin of the word "anarchism" is from the ancient Greek word "anarkhia", meaning "without a ruler", composed of the prefix "an-" (i.e. "without") and the word "arkhos" (i.e. "leader" or "ruler"). The suffix -ism denotes the ideological current that favours anarchy. The word "anarchism" appears in English from 1642 as "anarchisme" and the word "anarchy" from 1539. Various factions within the French Revolution labelled their opponents as "anarchists", although few such accused shared many views with later anarchists. Many revolutionaries of the 19th century such as William Godwin (17561836) and Wilhelm Weitling (18081871) would contribute to the anarchist doctrines of the next generation, but they did not use the word "anarchist" or "anarchism" in describing themselves or their beliefs.
The first political philosopher to call himself an "anarchist" () was Pierre-Joseph Proudhon (18091865), marking the formal birth of anarchism in the mid-19th century. Since the 1890s and beginning in France, the term "libertarianism" has often been used as a synonym for anarchism and its use as a synonym is still common outside the United States. On the other hand, some use "libertarianism" to refer to individualistic free-market philosophy only, referring to free-market anarchism as libertarian anarchism.
While opposition to the state is central to anarchist thought, defining anarchism is not an easy task as there is a lot of talk among scholars and anarchists on the matter and various currents perceive anarchism slightly differently. Hence, it might be true to say that anarchism is a cluster of political philosophies opposing authority and hierarchical organization (including the state, capitalism, nationalism and all associated institutions) in the conduct of all human relations in favour of a society based on voluntary association, on freedom and on decentralisation, but this definition has the same shortcomings as the definition based on etymology (which is simply a negation of a ruler), or based on anti-statism (anarchism is much more than that) or even the anti-authoritarian (which is an "a posteriori" conclusion). Nonetheless, major elements of the definition of anarchism include the following:
During the prehistoric era of mankind, an established authority did not exist. It was after the creation of towns and cities that institutions of authority were established and anarchistic ideas espoused as a reaction. Most notable precursors to anarchism in the ancient world were in China and Greece. In China, philosophical anarchism (i.e the discussion on the legitimacy of the state) was delineated by Taoist philosophers Zhuangzi and Lao Tzu. Likewise, anarchic attitudes were articulated by tragedians and philosophers in Greece. Aeschylus and Sophocles used the myth of Antigone to illustrate the conflict between rules set by the state and personal autonomy. Socrates questioned Athenian authorities constantly and insisted to the right of individual freedom of consciousness. Cynics dismissed human law ("nomos") and associated authorities while trying to live according to nature ("physis"). Stoics were supportive of a society based on unofficial and friendly relations among its citizens without the presence of a state.
During the Middle Ages, there was no anarchistic activity except some ascetic religious movements in the Islamic world or in Christian Europe. This kind of tradition later gave birth to religious anarchism. In Persia, Mazdak called for an egalitarian society and the abolition of monarchy, only to be soon executed by the king. In Basra, religious sects preached against the state. In Europe, various sects developed anti-state and libertarian tendencies. Libertarian ideas further emerged during the Renaissance with the spread of reasoning and humanism through Europe. Novelists fictionalised ideal societies that were based not on coercion but voluntarism. The Enlightenment further pushed towards anarchism with the optimism for social progress.
During the French Revolution, the partisan groups of Enrags and saw a turning point in the fermentation of anti-state and federalist sentiments. The first anarchist currents developed throughout the 18th centuryWilliam Godwin espoused philosophical anarchism in England, morally delegitimizing the state, Max Stirner's thinking paved the way to individualism, and Pierre-Joseph Proudhon's theory of mutualism found fertile soil in France. This era of classical anarchism lasted until the end of the Spanish Civil War of 1936 and is considered the golden age of anarchism.
Drawing from mutualism, Mikhail Bakunin founded collectivist anarchism and entered the International Workingmen's Association, a class worker union later known as the First International that formed in 1864 to unite diverse revolutionary currents. The International became a significant political force, and Karl Marx a leading figure and a member of its General Council. Bakunin's faction, the Jura Federation and Proudhon's followers, the mutualists, opposed Marxist state socialism, advocating political abstentionism and small property holdings. After bitter disputes the Bakuninists were expelled from the International by the Marxists at the 1872 Hague Congress. Bakunin famously predicted that if revolutionaries gained power by Marxist's terms, they would end up the new tyrants of workers. After being expelled, anarchists formed the St. Imier International. Under the influence of Peter Kropotkin, a Russian philosopher and scientist, anarcho-communism overlapped with collectivism. Anarcho-communists, who drew inspiration from the 1871 Paris Commune, advocated for free federation and distribution of goods according to one's needs.
At the turning of the century, anarchism had spread all over the world. In China, small groups of students imported the humanistic pro-science version of anarcho-communism. Tokyo was a hotspot for rebellious youth from countries of the far east, pouring into the Japanese capital to study. In Latin America, So Paulo was a stronghold for anarcho-syndicalism where it became the most prominent left-wing ideology. During this time, a minority of anarchists adopted tactics of revolutionary political violence. This strategy became known as propaganda of the deed. The dismemberment of the French socialist movement into many groups and the execution and exile of many Communards to penal colonies following the suppression of the Paris Commune favoured individualist political expression and acts. Even though many anarchists distanced themselves from these terrorist acts, infamy came upon the movement. Illegalism was another strategy which some anarchists adopted these same years.
Anarchists enthusiastically participated in the Russian Revolutiondespite concernsin opposition to the Whites. However, they met harsh suppression after the Bolshevik government was stabilized. Several anarchists from Petrograd and Moscow fled to Ukraine, notably leading to the Kronstadt rebellion and Nestor Makhno's struggle in the Free Territory. With the anarchists being crushed in Russia, two new antithetical currents emerged, namely platformism and synthesis anarchism. The former sought to create a coherent group that would push for the revolution while the latter were against anything that would resemble a political party. Seeing the victories of the Bolsheviks in the October Revolution and the resulting Russian Civil War, many workers and activists turned to communist parties which grew at the expense of anarchism and other socialist movements. In France and the United States, members of major syndicalist movements, the General Confederation of Labour and Industrial Workers of the World, left their organisations and joined the Communist International.
In the Spanish Civil War, anarchists and syndicalists (CNT and FAI) once again allied themselves with various currents of leftists. A long tradition of Spanish anarchism led to anarchists playing a pivotal role in the war. In response to the army rebellion, an anarchist-inspired movement of peasants and workers, supported by armed militias, took control of Barcelona and of large areas of rural Spain where they collectivised ''';
@@ -1,26 +0,0 @@
// This text is an extract from the Nepali Wikipedia article about Nepal
// (): https://ne.wikipedia.org/wiki/
//
// The extract is based on the Wikipedia database dump. All markup has been
// removed using WikiExtractor: https://github.com/attardi/wikiextractor
//
// The material is licensed under the Creative Commons Attribution-Share-Alike
// License 3.0: https://creativecommons.org/licenses/by-sa/3.0/
// @dart=2.9
const String ne = '''
(िि : ि ) ि ि िि ि ि २६ ि २२ िि ३० ि २७ ि ८० ि िि ८८ ि १२ ि ि ,४७,१८१ ि.ि .०३% ि .३% ि "ग्रीनवीच मिनटाइम" ि ि ८६ ि १५ ि ि ४५ ि ि ि
ि ि ८८५ ि.ि. ि ि ि ि ि २४१ ि.ि. १४५ ि.ि. १९३ ि.ि. ि ि ि, ि ८०% ि ि ि ि ि ि , , ि ि ि ि ि ि िि ि ि ि ि ि १४ ि , ि ( ) ि , ि िि , ि, , , , , ,
ि , ि ि ि ि 'ने' ि ि - ि , ि िि ि. . २०४६ ि ि ि िि ि ि ि िि १९९६ ि ...() ि िि ि
ि ि ि ि ि ि , १३,००० ि ि ि २००२ ि िि ि २००५ ि २००६ ि (-) ि २४, २००६ ि ि १८, २००६ ििि ि ि ि ि ि ि "सङ्घीय लोकतान्त्रिक गणराज्य, संविधानसभा" ि २८, २००८ िि
ि ि ि ि ,००० ि : - ि ,५०० ि
१५०० ि - ि १००० ि - ि ( ५६३४८३) , ि, ि ि
२५० , ''';
@@ -1,46 +0,0 @@
// This text is an extract from the Russian Wikipedia article about Lithuania
// (Литва): https://ru.wikipedia.org/wiki/Литва
//
// The extract is based on the Wikipedia database dump. All markup has been
// removed using WikiExtractor: https://github.com/attardi/wikiextractor
//
// The material is licensed under the Creative Commons Attribution-Share-Alike
// License 3.0: https://creativecommons.org/licenses/by-sa/3.0/
// @dart=2.9
const String ru = '''
Литва
Литва́ (), официальное название Лито́вская Респу́блика () государство, расположенное в северной части Европы. Столица страны Вильнюс.
Площадь км². Протяжённость с севера на юг 280 км, а с запада на восток 370 км. Население составляет человек (сентябрь, 2019). Занимает 140-е место место в мире по численности населения и 121-е по территории. Имеет выход к Балтийскому морю, расположена на его восточном побережье. Береговая линия составляет всего 99 км (наименьший показатель среди государств Балтии). На севере граничит с Латвией, на юго-востоке с Белоруссией, на юго-западе с Польшей и Калининградской областью России.
Член ООН с 1991 года, ЕС и НАТО с 2004 года, ОЭСР с мая 2018 года. Входит в Шенгенскую зону и Еврозону.
Независимость страны провозглашена 11 марта 1990 года, а юридически оформлена 6 сентября 1991 года. .
Этимология слова «Литва» точно не известна, при этом существует множество версий, ни одна из которых не получила всеобщего признания. Корень «лит» и его варианты «лет»/«лют» допускают различные толкования как в балтских и славянских, так и в других индоевропейских языках. Так, например, существуют созвучные топонимы на территории Словакии «"Lytva"» и Румынии «"Litua"», известные с XIXII веков. По мнению Е. Поспелова, топоним образован от древнего названия реки Летава (Lietavà от «лить», русское «Летаука»). Феодальное княжество, по землям которого протекала эта река, со временем заняло ведущее положение и название было распространено на всё государство. В «Повести временных лет» (XII век) упоминается этноним «литва», полностью совпадающий с названием местности «Литва» и по смыслу (территория, где живёт литва), и по форме.
Поверхность  равнинная со следами древнего оледенения. Поля и луга занимают 57 % территории, леса и кустарники  30 %, болота  6 %, внутренние воды  1 %.
Высшая точка  293,84 м над уровнем моря  холм Аукштояс (или Аукштасис калнас) в юго-восточной части страны, в 23,5 км от Вильнюса.
Крупнейшие реки  Неман и Вилия.
Более 3 тыс. озёр (1,5 % территории): крупнейшее из них  Друкшяй на границе Латвии, Литвы и Белоруссии (площадь 44,8 км²), самое глубокое  Таурагнас, 61 м), самое длинное  Асвея длинной в 30 км у местечка Дубингяй.
Климат переходный от морского к континентальному. Средняя температура зимой 5 °C, летом +17 °C. Выпадает 748 мм осадков в год.
Полезные ископаемые: торф, минеральные материалы, строительные материалы.
Территория современной Литвы была заселена людьми с конца XIX тысячелетия до н. э. Жители занимались охотой и рыболовством, использовали лук и стрелы с кремнёвыми наконечниками, скребки для обработки кожи, удочки и сети. В конце неолита (IIIII тысячелетия до н. э.) на территорию современной Литвы проникли индоевропейские племена. Они занимались земледелием и скотоводством, при этом охота и рыболовство оставались основными занятиями местных жителей вплоть до широкого распространения железных орудий труда. Индоевропейцы, заселившие земли между устьями Вислы и Западной Двины, выделились в отдельную группу, названную учёными балтами.
Традиционно считается, что этническая основа Литвы сформирована носителями археологической культуры восточнолитовских курганов, сложившейся в V веке н. э. на территории современных Восточной Литвы и Северо-Западной Белоруссии. Около VII века литовский язык отделился от латышского.
Становление государственности на территории современной Литвы относят к XIII веку, при этом само название «Литва» впервые упомянуто в Кведлинбургских анналах под 1009 годом в сообщении об убийстве язычниками миссионера Бруно на границе Руси и Литвы. По наиболее распространённой версии, топоним возник от названия небольшой реки Летаука, притока Няриса. Согласно более современной гипотезе, название страны могло произойти от этнонима «леты» или «лейти», которым жители окрестных земель называли дружинников литовских князей.
В начале XIII века в земли балтов-язычников с запада началось вторжение немецких рыцарей-крестоносцев. Они покорили Пруссию и Ливонию. В это же время с юга началась экспансия Галицко-Волынского княжества. К середине XIII века многие литовские земли были объединены под властью князя Миндовга, принявшего в 1251 году католическое крещение и коронованного в 1253 году. Через несколько лет Миндовг отрёкся от христианства и до начала XIV века литовские земли оставались языческими. Несмотря на то, что уже в 1263 году Миндовг был свергнут, его правление положило начало более чем пятисотлетнему существованию Великого княжества Литовского.
В XIV  начале XV веках территория Великого княжества Литовского стремительно росла, в основном за счёт присоединения земель Западной Руси. Включение в состав государства славянских земель, многократно превышающих по площади и количеству населения собственно литовские земли, привело к перениманию литовскими князьями, получившими во владение русские земли, православной культуры и западнорусского языка. Со временем западнорусский язык стал официальным языком канцелярии великих князей. Собственно литовский язык до XVI века оставался бесписьменным, хотя и продолжал использоваться на этнически литовских землях.
В 1385 году великий князь литовский Ягайло заключил Кревскую унию с Королевством Польским. По условиям унии, Ягайло обязался присоединить Великое княжество Литовское к Королевству Польскому и крестить литовские земли по католическому обряду, а сам становился королём Польши и сохранял титул великого князя литовского. Однако вскоре он вынужден был уступить власть в Великом княжестве Литовском своему двоюродному брату Витовту.''';
@@ -1,48 +0,0 @@
// This text is an extract from the Slovak Wikipedia article about Esperanto:
// https://sk.wikipedia.org/wiki/Esperanto
//
// The extract is based on the Wikipedia database dump. All markup has been
// removed using WikiExtractor: https://github.com/attardi/wikiextractor
//
// The material is licensed under the Creative Commons Attribution-Share-Alike
// License 3.0: https://creativecommons.org/licenses/by-sa/3.0/
// @dart=2.9
const String sk = '''
Esperanto (pôvodne Lingvo Internacia medzinárodný jazyk) je najrozšírenejší medzinárodný plánový jazyk. Názov je odvodený od pseudonymu, pod ktorým v roku 1887 zverejnil lekár L. L. Zamenhof základy tohto jazyka. Zámerom tvorcu bolo vytvoriť ľahko naučiteľný a použiteľný neutrálny jazyk, vhodný na použitie v medzinárodnej komunikácii. Cieľom nebolo nahradiť národné jazyky, čo bolo neskôr aj deklarované v Boulonskej deklarácii.
Hoci žiaden štát neprijal esperanto ako úradný jazyk, používa ho komunita s odhadovaným počtom hovoriacich 100 000 2 000 000, z čoho približne 2 000 tvoria rodení hovoriaci. V Poľsku je na zozname nemateriálneho kultúrneho dedičstva. Získalo aj isté medzinárodné uznania, napríklad dve rezolúcie UNESCO či podporu známych osobností verejného života. V súčasnosti sa esperanto využíva pri cestovaní, korešpondencii, medzinárodných stretnutiach a kultúrnych výmenách, kongresoch, vedeckých diskusiách, v pôvodnej aj prekladovej literatúre, divadle a kine, hudbe, tlačenom aj internetovom spravodajstve, rozhlasovom a televíznom vysielaní.
Slovná zásoba esperanta pochádza predovšetkým zo západoeurópskych jazykov, zatiaľ čo jeho skladba a tvaroslovie ukazujú na silný slovanský vplyv. Morfémy nemenné a je možné ich kombinovať takmer bez obmedzení do rozmanitých slov; esperanto teda mnoho spoločného s analytickými jazykmi, ako je čínština, zatiaľ čo vnútorná stavba jeho slov pripomína jazyky aglutinačné, ako je japončina, swahilčina alebo turečtina.
Pri zrode esperanta stál Ludwik Lejzer Zamenhof. Vyrastal v mnohojazyčnom, vtedy ruskom, teraz poľskom meste Białystok, kde bol svedkom častých sporov medzi jednotlivými národnosťami (Rusi, Poliaci, Nemci, Židia). Pretože za jednu z hlavných príčin týchto sporov považoval neexistenciu spoločného jazyka, začal ako školák pracovať na projekte reči, ktorá by túto funkciu mohla plniť. Mala byť, na rozdiel od národných jazykov, neutrálna a ľahko naučiteľná, teda prijateľná ako druhý jazyk pre všetkých, jazyk vyučovaný spoločne s národnými jazykmi a používaný v situáciách vyžadujúcich dorozumenie medzi národmi.
Zamenhof najskôr uvažoval o oživení latinčiny, ktorú sa učil v škole, ale usúdil, že je pre bežné dorozumievanie zbytočne zložitá. Keď študoval angličtinu, všimol si, že časovanie slovies podľa osoby a čísla nie je nutné; že gramatický systém jazyka môže byť oveľa jednoduchší, než sa dovtedy nazdával. Stále však zostávala prekážka v memorovaní sa veľkého množstva slov. Raz Zamenhofa zaujali dva ruské nápisy: "швейцарская" [švejcarskaja] (vrátnica, odvodené od "швейцар" [švejcar] vrátnik) a "кондитерская" [konditerskaja] (cukráreň, odvodené od "кондитер" [konditér] cukrár). Tieto slová rovnakého zakončenia mu vnukli myšlienku, že používanie pravidelných predpôn a prípon by mohlo významne znížiť množstvo slovných koreňov nutných na dorozumenie sa. Aby boli korene čo najmedzinárodnejšie, rozhodol sa prevziať slovnú zásobu predovšetkým z románskych a germánskych jazykov, teda tých, ktoré boli vtedy v školách po celom svete vyučované najčastejšie.
Prvý Zamenhofov projekt, nazvaný "Lingwe uniwersala," bol viac-menej hotový v roku 1878, ale autorov otec, učiteľ jazykov, považoval túto prácu za márnu a utopistickú, a zrejme preto rukopis, ktorý mu bol zverený, zničil. V rokoch 1879  1885 Zamenhof študoval medicínu v Moskve a vo Varšave. V tej dobe začal znova pracovať na medzinárodnom jazyku. Prvú obnovenú verziu vyučoval v roku 1879 pre svojich priateľov. Po niekoľkých rokoch prekladal poéziu, aby jazyk čo najviac zdokonalil. V roku 1885 autor napísal:
Zamenhofovi prichádzalo veľa nadšených listov, ktoré často prinášali najrôznejšie návrhy úprav jazyka. Všetky podnety zaznamenával a neskoršie ich začal uverejňovať v časopise "Esperantisto", vychádzajúcom v Norimbergu. V tom istom časopise aj dal o úpravách dvakrát hlasovať, väčšina čitateľov však so zmenami nesúhlasila. Po týchto hlasovaniach na určitý čas utíchli hlasy volajúce po reforme a jazyk sa začal rozširovať. Najviac odberateľov mal časopis vo vtedajšom Rusku. Veľkou ranou preň bolo, keď ruská cenzúra jeho šírenie zakázala kvôli článku Leva Nikolajeviča Tolstého. Časopis kvôli tomu musel byť zrušený, krátko na to bol však vystriedaný novým, nazvaným "Lingvo Internacia." Najskôr ho redigovali vo švédskej Uppsale, neskôr v Maďarsku a nakoniec v Paríži, kde jeho vydávanie zastavila prvá svetová vojna.
Nový medzinárodný jazyk začali jeho používatelia skoro používať aj na organizáciu odbornej a záujmovej činnosti na medzinárodnej úrovni. V prvých desaťročiach prebiehala komunikácia v esperante takmer výhradne písomnou formou. Ale po nečakane úspešnom prvom Svetovom kongrese esperanta, usporiadanom v roku 1905 vo francúzskom meste Boulogne-sur-Mer, na ktorom sa overili možnosti používania tejto reči v hovorenej forme, začali naberať na intenzite aj osobné kontakty.
Esperanto začali pre svoju činnosť používať aj rôzne organizácie a hnutia. na svetovom kongrese v Barcelone roku 1909 sa uskutočnilo niekoľko stretnutí prítomných katolíkov, ktorí sa nakoniec rozhodli usporiadať v nadchádzajúcom roku, 1910, samostatný kongres katolíckych esperantistov. Počas neho bolo založené Medzinárodné združenie katolíckych esperantistov (IKUE Internacia Katolika Unuiĝo Esperantista). Časopis "Espero Katolika" ("Katolícka nádej") vychádzal od roku 1903 a s viac ako 100 rokmi svojej existencie je dnes najdlhšie vychádzajúcim esperantským periodikom.
V roku 1912 sa Zamenhof pri slávnostnom prejave ôsmeho Svetového kongresu esperanta v Krakove vzdal svojej oficiálnej úlohy v hnutí. Desiaty kongres sa mal konať v roku 1914 v Paríži, prihlásilo sa naň takmer 4 000 ľudí, ale nakoniec ho zrušili pre začínajúcu vojnu, Zamenhof sa vtedy musel vrátiť domov cez škandinávske štáty.
Po vojne túžba po harmónii a mieri vzbudila nové nádeje, vďaka čomu sa esperanto veľmi rýchlo šírilo. Prvý povojnový kongres sa konal v roku 1920 v Haagu, 13. svetový kongres v 1921 v Prahe. V roku 1927 bolo vo viedenskom Hofburgu otvorené Medzinárodné esperantské múzeum, v roku 1929 bolo pripojené k Rakúskej národnej knižnici a dnes sídli v samostatnej budove.
Snahy o presadenie esperanta ako univerzálneho jazyka sa stretávali s pozitívnou odozvou: Petíciu v jeho prospech adresovanú Organizácii Spojených národov podpísalo vyše 80 miliónov ľudí, v Česko-Slovensku napríklad prof. Jaroslav Heyrovský, nositeľ Nobelovej ceny.
Valné zhromaždenie UNESCO prijalo podobné rezolúcie v Montevideu 10. decembra 1954 a v Sofii 8. novembra 1985. Vzalo v nich na vedomie "výsledky dosiahnuté esperantom na poli medzinárodnej duchovnej výmeny aj zblíženia národov sveta" a vyzvalo členské štáty, "aby sa chopili iniciatívy pri zavádzaní študijných programov o jazykovom probléme a esperante na svojich školách a inštitúciách vyššieho vzdelávania".
K esperantu sa hlásila aj rada predsedov Poľskej akadémie vied. Jubilejného 72. Svetového kongresu esperanta roku 1987 (100. výročie uverejnenia prvej učebnice jazyka) sa vo Varšave zúčastnilo takmer 6 000 ľudí zo 60 národov.
Pokroky dosiahli aj katolícki esperantisti roku 1990 bol vydaný dokument "Norme per la celebrazione della Messa in esperanto", ktorým Svätá stolica povoľuje vysluhovať sväté omše v tomto jazyku bez zvláštneho povolenia. Esperanto sa tak stalo jediným schváleným umelým liturgickým jazykom katolíckej cirkvi.
Skutočnosť, že mnohé z cieľov esperantského hnutia sa doteraz nepodarilo naplniť, je často prisudzovaná okrem iného technologickej a kultúrnej dominancii Spojeného kráľovstva a Spojených štátov amerických, predovšetkým v období po druhej svetovej vojne, vďaka čomu je v súčasnosti dorozumievacím jazykom väčšiny medzinárodných činností angličtina.
na začiatku 20. storočia bolo na území dnešného Slovenska (vtedy severná časť Uhorska) činné esperantské hnutie. Esperantistov a kluby zastrešovala Uhorská esperantská spoločnosť a Verda Standardo. V Prahe boli činné spolky "Bohema Unio Esperantista", ktorý prijímal len organizácie a kluby, a "Bohema Asocio Esperantista", ktorý prijímal jednotlivcov. Oba spolky vydávali svoje časopisy. V roku 1907, 20 rokov po zverejnení jazyka Zamenhofom, vydal tolstojovec Albert Škarvan spolu s Rusom N. P. Evstifejevom prvú učebnicu esperanta v slovenčine, Základy medzinárodnej reči ESPERANTO.
Po prvej svetovej vojne sa oba pražské spolky zlúčili do "Československej Esperantskej Asociácie". bola v roku 1936 premenovaná na "Esperantskú Asociáciu v Československej republike". V tomto období bolo hnutie veľmi aktívne, fungovalo mnoho klubov, konalo sa veľa prednášok a kurzov. Esperanto bolo vyučované na školách rôznych stupňov, rádio Bratislava od 1930 vysielalo kurzy a od 1932 aj kultúrny program v esperante. Bola vydaná "Československá antológia" predstavujúca diela 20 slovenských autorov. V rámci protifašistickej aktivity vychádzali aj preklady protifašistických článkov z esperantských časopisov z obdobia Španielskej občianskej vojny.
Druhá svetová vojna utlmila esperantské hnutie. Bratislavský esperantský klub požiadal o zmenu štatútu a rozšírenie poľa pôsobnosti na celú vtedajšiu Slovenskú republiku a následne sa stal strediskom esperantského hnutia na Slovensku.''';
@@ -1,75 +0,0 @@
// This text is an extract from the Chinese Wikipedia article about Kanji
// (): https://zh.wikipedia.org/wiki/
//
// The extract is based on the Wikipedia database dump. All markup has been
// removed using WikiExtractor: https://github.com/attardi/wikiextractor
//
// The material is licensed under the Creative Commons Attribution-Share-Alike
// License 3.0: https://creativecommons.org/licenses/by-sa/3.0/
// @dart=2.9
const String zh = '''
丿𠄌𠃋𠃉𠃊
5471-{}-6464-{}-𠔻52
TRON计划中使3-{}-3-{}-84C区JMK66147C区的时间原因被安排到了扩展D区G区并被接受
西Unicode中它們都是獨立區塊編碼的
Unicode中與漢字一道編入漢字區
Unicode中作為獨立區塊編碼
滿
使
滿
使使使使使使
3使使-{}--{}--{}--{}--{}--{}-
3使-l
1443使使2011使1948
1便使便
1945使
使
西
使
-{}--{}-
使-{}--{}--{}--{}--{}--{}-
1956-{}--{}-1988-{}--{}--{}--{}--{}--{}-
26
OCR广
GB 2312B''';
@@ -1,99 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
// Benchmark for UTF-8 encoding
// @dart=2.9
import 'dart:convert';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'datext_latin1_10k.dart';
import 'entext_ascii_10k.dart';
import 'netext_3_10k.dart';
import 'rutext_2_10k.dart';
import 'sktext_10k.dart';
import 'zhtext_10k.dart';
class Utf8Encode extends BenchmarkBase {
final String language;
final String originalText;
// Size is measured in number of runes rather than number of bytes.
// This differs from the Utf8Decode benchmark, but runes are the input
// to the encode function which makes them more natural than bytes here.
final int size;
List<String> benchmarkTextChunks;
static String _makeName(String language, int size) {
String name = 'Utf8Encode.$language.';
name +=
size >= 1000000
? '${size ~/ 1000000}M'
: size >= 1000
? '${size ~/ 1000}k'
: '$size';
return name;
}
Utf8Encode(this.language, this.originalText, this.size)
: super(_makeName(language, size));
@override
void setup() {
final int nRunes = originalText.runes.toList().length;
final String repeatedText = originalText * (size / nRunes).ceil();
final List<int> runes = repeatedText.runes.toList();
final int nChunks = (size < nRunes) ? (nRunes / size).floor() : 1;
benchmarkTextChunks = List<String>.filled(nChunks, null);
for (int i = 0; i < nChunks; i++) {
final offset = i * size;
benchmarkTextChunks[i] = String.fromCharCodes(
runes.sublist(offset, offset + size),
);
}
}
@override
void run() {
for (int i = 0; i < benchmarkTextChunks.length; i++) {
final encoded = utf8.encode(benchmarkTextChunks[i]);
if (encoded.length < benchmarkTextChunks[i].length) {
throw 'There should be at least as many encoded bytes as runes';
}
}
}
@override
void exercise() {
// Only a single run per measurement.
run();
}
@override
double measure() {
// Report time per input rune.
return super.measure() / size / benchmarkTextChunks.length;
}
@override
void report() {
// Report time in nanoseconds.
final double score = measure() * 1000.0;
print('$name(RunTime): $score ns.');
}
}
void main(List<String> args) {
const texts = {'en': en, 'da': da, 'sk': sk, 'ru': ru, 'ne': ne, 'zh': zh};
final benchmarks = [
for (int size in [10, 10000, 10000000])
for (String language in texts.keys)
() => Utf8Encode(language, texts[language], size),
];
for (var bm in benchmarks) {
bm().report();
}
}
@@ -1,64 +0,0 @@
// This text is an extract from the Danish Wikipedia article about Donald Duck
// (Anders And): https://da.wikipedia.org/wiki/Anders_And
//
// The extract is based on the Wikipedia database dump. All markup has been
// removed using WikiExtractor: https://github.com/attardi/wikiextractor
//
// The material is licensed under the Creative Commons Attribution-Share-Alike
// License 3.0: https://creativecommons.org/licenses/by-sa/3.0/
// @dart=2.9
const String da = '''
Anders And
Anders Fauntleroy And er en berømt figur i Disneys tegnefilm og tegneserier. Selv om han ikke er særligt populær i USA, optræder han i mange ugeblade i Europa: I Norge, Tyskland, Sverige, Danmark, Holland, Italien med flere. Hans første optræden var i tegnefilmen "The Wise Little Hen" (Den kloge lille høne) fra 9. juni 1934. Hans karakteristiske stemme blev indtalt af radiokomikeren Clarence Nash, der siden fast lagde stemme til.
Efter Nash' død i 1985 overtog tegnefilmsdubberen Tony Anselmo. Det var i øvrigt Nash selv, der trænede Anselmo til at lyde som Anders And. I Danmark har tre lagt stemme til Anders And: Bjarne H. Hansen, Dick Kaysø og Peter Zhelder. Dick Kaysø og Peter Zhelder lægger stadigvæk stemme til ham.
Anders And var en bifigur til filmen Den lille kloge Høne, han havde et langt spidst næb og en utrolig kort lunte; der skulle ikke meget til for at udløse et raserianfald hos ham. Klassikerne er fra 1930'erne, hvor Mickey, Fedtmule og Anders er et trekløver, der er film som "Mickeys Campingvogn," "Tårnuret" og "Ensomme Spøgelser." Fred Spencer og Dick Lundy var animatorer. Efterhånden opnåede anden større popularitet, hvad der ikke rigtig huede Disney, der ikke brød sig om den krakilske and. Men Anders blev forfremmet til hovedfigur i en serie film, der begyndte med "Anders And og Strudsen" i 1938. Med den var det "ande-teamet" hos Disney født: instruktøren Jack King og assistenterne Carl Barks (den senere serieskaber), Chuck Couch, Harry Reeves og Jack Hannah. Han var stadigvæk en hidsigprop, men han blev gjort mere nuanceret, og nye figurer blev tilføjet som nevøerne Rip, Rap og Rup, kæresten Andersine And og i en enkelt film Fætter Guf.
Under 2. verdenskrig blev der lavet film om anden i militærtjeneste, som han selvfølgelig gør meget klodset. Mest kendt er "Der Fuehrers Face" fra 1943, hvor anden drømmer, at han er i diktaturstaten Nutziland. Den film blev arkiveret af Disney efter krigen, men er senere vist meget uofficielt. Desuden medvirkede han i to mindre kendte spillefilm "Saludos Amigos" 1943 og "The Three Caballeros" 1945, der gav et lystigt billede af livet i Latinamerika.
Efter krigen blev omgivelserne mere hjemlige, men næppe mere fredfyldte. I 1947 overtog Jack Hannah pladsen som instruktør. Filmene handlede ofte om klammeri med andre, det kunne være en bi, Chip og Chap eller bare ting han ikke kunne til at makke ret. Anders var her ofte plageånden, hvis egne drillerier kom tilbage som en boomerang.
Fjernsynets fremmarch i 1950'erne satte snart stopper for de korte tegnefilm, og Jack Hannah blev sat til at redigere Disneys tv-shows og kæde de korte tegnefilm sammen i et længere forløb. Her blev Anders gjort mere sympatisk, men det var eksperten i alt, Raptus von And, der gjorde mest for tv-showet. I et andet tv-show Disney Sjov medvirkede Anders i tv-serierne Rip, Rap og Rup på eventyr, Bonkers, og Rap Sjak. I Rip, Rap og Rup på eventyr, var han sjældent med, men fik et nyt tøj. I Rap Sjak var hans matrostøj skiftet ud med en hawaii-skjorte med røde og hvide blomster. I Bonkers var han også med kort tid.
Anders And gik til tegneserien allerede tidligt efter sin debut i 1934, hvor han i avisstriber optrådte med sin makker fra "The Wise Little Hen," Peter Gris. Fra den 10. februar 1935 blev han en del af Mickeys avisstribe som musens kujonagtige og drillesyge ven, men fra 1936 kaprede han hovedrollen i Silly Symphony-striben. Forfatteren Ted Osborne og tegneren Al Taliaferro, der stod bag serieudgaven af The Wise Little Hen, pressede , og da det blev en succes kunne forfatteren Bob Karp i samarbejde med Taliaferro lave andens egen avisstribe.
Det blev en populær serie. I de allertidligste serier var Anders en hidsig, ondskabsfuld og pueril and med langt spidst næb og hænder, der knap kunne skelnes fra vinger. Senere blev han mere voksen, da han fik ansvaret for sine tre nevøer Rip, Rap og Rup, og kæresten Andersine kom til sammen med Bedstemor And.
Tegneseriefiguren Anders And blev senere udviklet yderligere af Carl Barks. I de tidlige tegnefilm var han for det meste doven og hidsig; men for at gøre hans figur brugbar til en tegneserie besluttede Barks at udvide hans personlighed. Anders' mest gennemgående karaktertræk er hans notoriske uheld, som desuden har den narrative funktion at give adgang til spændende eventyr, uden at serien udvikler sig for meget. På denne måde kan Anders eksempelvis blive involveret i alverdens skattejagter, og da han altid ender med at miste den fundne gevinst, kan alle historierne starte fra samme udgangspunkt.
For at give Anders en verden at bo i, skabte Barks byen Andeby i den amerikanske stat Calisota (som er en blanding af de to amerikanske stater Californien og Minnesota) med indbyggere som den rige onkel Joakim von And, den heldige Fætter Højben og den dygtige opfinder Georg Gearløs.
Anders lægger med sit engelske navn Donald Duck i øvrigt navn til donaldismen, fankulturen omkring Disney-tegneserier og -tegnefilm, som den norske forfatter Jon Gisle udviklede med sin bog af samme navn.
Anders bor i Andeby Paradisæblevej 111 med sine tre nevøer Rip, Rap og Rup. De er stort set identiske, men de kan i nogle historier identificeres , hvilken farve kasket de har .
Ifølge Disneytegneserieforfatteren Don Rosa var Anders født et eller andet sted omkring 1920 men dette er "ikke" officielt. Ifølge Carl Barks' stamtræ (senere udviklet og genbygget af Don Rosa for den danske udgiver Egmont Serieforlaget) er Anders' forældre Hortensia von And og Rapmus And. Anders har en søster ved navn Della And, men hverken hun eller Anders' forældre optræder i tegnefilmene eller tegneserierne bortset fra særlige steder som eksempelvis i Her er dit liv, Joakim. Ifølge Don Rosa er Anders og Della tvillinger.
Fra tegnefilmen "Mr. Duck Steps Out" har Anders' kæreste været Andersine And, men han går i stadig fare for at miste hende til den heldige Fætter Højben. I nogle italienske historier er Anders også superhelt under dæknavnet "Stålanden".
Anders' onkel, Joakim von And, er den rigeste and i verden.
Sammen med onkelen og nevøerne Rip, Rap og Rup har Anders And rejst jorden rundt til mange forskellige lande og steder. Blandt disse er landet Langtbortistan, hvis navn blev opfundet af den danske oversætter Sonja Rindom og senere er gledet ind i almindeligt, dansk sprogbrug.
I de tidlige historier af Carl Barks havde Anders en hale, der stak langt bagud. Han havde langt næb og lang hals, og hans matrostrøje havde fire knapper. Hans lange hals passede godt til egenskaben nysgerrighed og det lange næb til hans hidsighed, hvilket var to egenskaber, der prægede ham mest. Disse tidlige historier var også præget af en grov komik i stil med tegnefilmene.
Siden fik han et mere strømlinet udseende og kortere næb (dog ikke kort som visse tegnere i 1960'erne gjorde det!) og kun to knapper på trøjen, et udseende de øvrige andetegnere også tager til sig. Her blev hans natur også mere sammensat, og han ligner mest af alt en tragisk helt. Komikken kommer mere og mere til at ligge i replikkerne.
Anders And optræder særligt i jumbobøgerne med en hemmelig identitet i form af superhelten Stålanden. Figuren er inspireret af Batman og er skabt af den italienske forfatter Guido Martina i samarbejde med kunstneren Giovan Battista Carpi i 1969 i hans italienske navn Paperinik. Ofte tegnet af Romano Scarpa.
I lighed med inspirationskilden er han maskeret og har et hav af tekniske opfindelser, som han bruger i kamp mod forbryderne og overvejende! i kamp for at redde sit andet jeg, Anders And, ud af kniben. Den eneste, som kender hans hemmelige identitet, er opfinderen Georg Gearløs, som har udstyret gamle 313 med moderne udstyr og finurligheder. Det er ikke tit at Stålanden optræder; næsten kun i Jumbobøger, men har dog også optrådt i Anders And-bladene med en gæstehistorie, hvor Stålanden kæmper mod en tidligere fjende, som nu havde kaldt sig Lord Hvalros.
Efter at Stålanden i starten af 1990'erne ikke var benyttet så meget af historieskriverne, forsvandt han næsten ud af Disney-universet indtil 1996, hvor en ny serie, "Stålanden på nye eventyr", startede med Stålanden i hovedrollen (umiddelbart inspireret af Marvel universet). Denne relancering af Stålanden gav karakteren det ekstra, der skulle til for at få et godt comeback.
I modsætning til størstedelen af Anders And-tegneserier har denne serie en sammenhængende forløb. I serien optræder kun sjældent de andre figurer fra de normale Anders And tegneserier; oftest er det kun en kort birolle eller en reference, men til gengæld er en mængde nye figurer kommet til.
Serien starter med, at Anders And er ansat som vicevært i Ducklair Tower, et højhus bygget af mangemilliardæren Everett Ducklair, en fremragende videnskabsmand og opfinder, som forlod Andeby og drog til et tibetansk kloster, Dhasam-Bul. Anders finder Globus, en kunstig intelligens skabt af Ducklair, samt Ducklair's arsenal af våben og opfindelser. Dette bliver starten på Anders' liv som Stålanden.
En mængde temaer var ofte i centrum for historierne, bl.a. tidsrejser og Tidspolitiets kamp med tidspiraterne fra Organisationen, invasion fra rummet af de magtsyge evronianere, Stålandens samarbejde med FBI og meget mere.
Serien fik en fornyelse i 2001, hvilket ændrede markant historierne. Everett Ducklair vender tilbage, slukker Globus, smider Stålanden ud af Ducklair Tower og genopretter sit gamle imperium. Undervejs bliver Ducklair's to døtre afsløret. De hader begge Everett af grunde, der ikke bliver afsløret til fulde, selvom det bliver antydet, at Everett skilte sig af med deres mor på en eller anden måde.
Denne fornyelse holdt 18 numre, før serien blev afsluttet, dog uden at historierne fik en slutning.
Barks-historien "Anders And og den gyldne hjelm" fra 1954 kom i 2006 med i ''';
@@ -1,37 +0,0 @@
// This text is an extract from the English Wikipedia article about Anarchism:
// https://en.wikipedia.org/wiki/Anarchism
//
// The extract is based on the Wikipedia database dump. All markup has been
// removed using WikiExtractor: https://github.com/attardi/wikiextractor
//
// The material is licensed under the Creative Commons Attribution-Share-Alike
// License 3.0: https://creativecommons.org/licenses/by-sa/3.0/
// @dart=2.9
const String en = '''
Anarchism
Anarchism is a radical political movement that is highly skeptical towards authority and rejects all forms of unjust hierarchy. It calls for the abolition of the state which it holds to be undesirable, unnecessary, and harmful. Anarchism advocates for the replacement of the state with stateless societies or other forms of free associations.
Anarchism's timeline stretches back to prehistory when people lived in anarchistic societies long before the establishment of formal states, kingdoms or empires. With the rise of organised hierarchical bodies, skepticism towards authority also rose, but it was not until the 19th century a self-conscious political movement was formed. During the latest half of 19th and the first decades of 20th century, the anarchist movement flourished to most parts of the world, and had a significant role in worker's struggles for emancipation. Various branches of anarchism were espoused during those times. Anarchists took part in several revolutions, most notably in the Spanish Civil War, where they were crushed by the fascists forces in 1939, marking the end of the classical era of anarchism. In the latest decades of the 20th century, the anarchist movement nonetheless became relevant and vivid once more.
Anarchism employ various tactics in order to meet their ideal ends; these can be broadly separated in revolutionary and evolutionary tactics. There is significant overlap between the two legs which are merely descriptive. Revolutionary tactics aim to bring down authority and state, and have taken a violent turn in the past. Evolutionary tactics aim to prefigure what an anarchist society would be like. Anarchism's thought, criticism and praxis has played a part in diverse fields of human society.
The etymological origin of the word "anarchism" is from the ancient Greek word "anarkhia", meaning "without a ruler", composed of the prefix "an-" (i.e. "without") and the word "arkhos" (i.e. "leader" or "ruler"). The suffix -ism denotes the ideological current that favours anarchy. The word "anarchism" appears in English from 1642 as "anarchisme" and the word "anarchy" from 1539. Various factions within the French Revolution labelled their opponents as "anarchists", although few such accused shared many views with later anarchists. Many revolutionaries of the 19th century such as William Godwin (17561836) and Wilhelm Weitling (18081871) would contribute to the anarchist doctrines of the next generation, but they did not use the word "anarchist" or "anarchism" in describing themselves or their beliefs.
The first political philosopher to call himself an "anarchist" () was Pierre-Joseph Proudhon (18091865), marking the formal birth of anarchism in the mid-19th century. Since the 1890s and beginning in France, the term "libertarianism" has often been used as a synonym for anarchism and its use as a synonym is still common outside the United States. On the other hand, some use "libertarianism" to refer to individualistic free-market philosophy only, referring to free-market anarchism as libertarian anarchism.
While opposition to the state is central to anarchist thought, defining anarchism is not an easy task as there is a lot of talk among scholars and anarchists on the matter and various currents perceive anarchism slightly differently. Hence, it might be true to say that anarchism is a cluster of political philosophies opposing authority and hierarchical organization (including the state, capitalism, nationalism and all associated institutions) in the conduct of all human relations in favour of a society based on voluntary association, on freedom and on decentralisation, but this definition has the same shortcomings as the definition based on etymology (which is simply a negation of a ruler), or based on anti-statism (anarchism is much more than that) or even the anti-authoritarian (which is an "a posteriori" conclusion). Nonetheless, major elements of the definition of anarchism include the following:
During the prehistoric era of mankind, an established authority did not exist. It was after the creation of towns and cities that institutions of authority were established and anarchistic ideas espoused as a reaction. Most notable precursors to anarchism in the ancient world were in China and Greece. In China, philosophical anarchism (i.e the discussion on the legitimacy of the state) was delineated by Taoist philosophers Zhuangzi and Lao Tzu. Likewise, anarchic attitudes were articulated by tragedians and philosophers in Greece. Aeschylus and Sophocles used the myth of Antigone to illustrate the conflict between rules set by the state and personal autonomy. Socrates questioned Athenian authorities constantly and insisted to the right of individual freedom of consciousness. Cynics dismissed human law ("nomos") and associated authorities while trying to live according to nature ("physis"). Stoics were supportive of a society based on unofficial and friendly relations among its citizens without the presence of a state.
During the Middle Ages, there was no anarchistic activity except some ascetic religious movements in the Islamic world or in Christian Europe. This kind of tradition later gave birth to religious anarchism. In Persia, Mazdak called for an egalitarian society and the abolition of monarchy, only to be soon executed by the king. In Basra, religious sects preached against the state. In Europe, various sects developed anti-state and libertarian tendencies. Libertarian ideas further emerged during the Renaissance with the spread of reasoning and humanism through Europe. Novelists fictionalised ideal societies that were based not on coercion but voluntarism. The Enlightenment further pushed towards anarchism with the optimism for social progress.
During the French Revolution, the partisan groups of Enrags and saw a turning point in the fermentation of anti-state and federalist sentiments. The first anarchist currents developed throughout the 18th centuryWilliam Godwin espoused philosophical anarchism in England, morally delegitimizing the state, Max Stirner's thinking paved the way to individualism, and Pierre-Joseph Proudhon's theory of mutualism found fertile soil in France. This era of classical anarchism lasted until the end of the Spanish Civil War of 1936 and is considered the golden age of anarchism.
Drawing from mutualism, Mikhail Bakunin founded collectivist anarchism and entered the International Workingmen's Association, a class worker union later known as the First International that formed in 1864 to unite diverse revolutionary currents. The International became a significant political force, and Karl Marx a leading figure and a member of its General Council. Bakunin's faction, the Jura Federation and Proudhon's followers, the mutualists, opposed Marxist state socialism, advocating political abstentionism and small property holdings. After bitter disputes the Bakuninists were expelled from the International by the Marxists at the 1872 Hague Congress. Bakunin famously predicted that if revolutionaries gained power by Marxist's terms, they would end up the new tyrants of workers. After being expelled, anarchists formed the St. Imier International. Under the influence of Peter Kropotkin, a Russian philosopher and scientist, anarcho-communism overlapped with collectivism. Anarcho-communists, who drew inspiration from the 1871 Paris Commune, advocated for free federation and distribution of goods according to one's needs.
At the turning of the century, anarchism had spread all over the world. In China, small groups of students imported the humanistic pro-science version of anarcho-communism. Tokyo was a hotspot for rebellious youth from countries of the far east, pouring into the Japanese capital to study. In Latin America, So Paulo was a stronghold for anarcho-syndicalism where it became the most prominent left-wing ideology. During this time, a minority of anarchists adopted tactics of revolutionary political violence. This strategy became known as propaganda of the deed. The dismemberment of the French socialist movement into many groups and the execution and exile of many Communards to penal colonies following the suppression of the Paris Commune favoured individualist political expression and acts. Even though many anarchists distanced themselves from these terrorist acts, infamy came upon the movement. Illegalism was another strategy which some anarchists adopted these same years.
Anarchists enthusiastically participated in the Russian Revolutiondespite concernsin opposition to the Whites. However, they met harsh suppression after the Bolshevik government was stabilized. Several anarchists from Petrograd and Moscow fled to Ukraine, notably leading to the Kronstadt rebellion and Nestor Makhno's struggle in the Free Territory. With the anarchists being crushed in Russia, two new antithetical currents emerged, namely platformism and synthesis anarchism. The former sought to create a coherent group that would push for the revolution while the latter were against anything that would resemble a political party. Seeing the victories of the Bolsheviks in the October Revolution and the resulting Russian Civil War, many workers and activists turned to communist parties which grew at the expense of anarchism and other socialist movements. In France and the United States, members of major syndicalist movements, the General Confederation of Labour and Industrial Workers of the World, left their organisations and joined the Communist International.
In the Spanish Civil War, anarchists and syndicalists (CNT and FAI) once again allied themselves with various currents of leftists. A long tradition of Spanish anarchism led to anarchists playing a pivotal role in the war. In response to the army rebellion, an anarchist-inspired movement of peasants and workers, supported by armed militias, took control of Barcelona and of large areas of rural Spain where they collectivised ''';
@@ -1,26 +0,0 @@
// This text is an extract from the Nepali Wikipedia article about Nepal
// (): https://ne.wikipedia.org/wiki/
//
// The extract is based on the Wikipedia database dump. All markup has been
// removed using WikiExtractor: https://github.com/attardi/wikiextractor
//
// The material is licensed under the Creative Commons Attribution-Share-Alike
// License 3.0: https://creativecommons.org/licenses/by-sa/3.0/
// @dart=2.9
const String ne = '''
(िि : ि ) ि ि िि ि ि २६ ि २२ िि ३० ि २७ ि ८० ि िि ८८ ि १२ ि ि ,४७,१८१ ि.ि .०३% ि .३% ि "ग्रीनवीच मिनटाइम" ि ि ८६ ि १५ ि ि ४५ ि ि ि
ि ि ८८५ ि.ि. ि ि ि ि ि २४१ ि.ि. १४५ ि.ि. १९३ ि.ि. ि ि ि, ि ८०% ि ि ि ि ि ि , , ि ि ि ि ि ि िि ि ि ि ि ि १४ ि , ि ( ) ि , ि िि , ि, , , , , ,
ि , ि ि ि ि 'ने' ि ि - ि , ि िि ि. . २०४६ ि ि ि िि ि ि ि िि १९९६ ि ...() ि िि ि
ि ि ि ि ि ि , १३,००० ि ि ि २००२ ि िि ि २००५ ि २००६ ि (-) ि २४, २००६ ि ि १८, २००६ ििि ि ि ि ि ि ि "सङ्घीय लोकतान्त्रिक गणराज्य, संविधानसभा" ि २८, २००८ िि
ि ि ि ि ,००० ि : - ि ,५०० ि
१५०० ि - ि १००० ि - ि ( ५६३४८३) , ि, ि ि
२५० , ''';
@@ -1,46 +0,0 @@
// This text is an extract from the Russian Wikipedia article about Lithuania
// (Литва): https://ru.wikipedia.org/wiki/Литва
//
// The extract is based on the Wikipedia database dump. All markup has been
// removed using WikiExtractor: https://github.com/attardi/wikiextractor
//
// The material is licensed under the Creative Commons Attribution-Share-Alike
// License 3.0: https://creativecommons.org/licenses/by-sa/3.0/
// @dart=2.9
const String ru = '''
Литва
Литва́ (), официальное название Лито́вская Респу́блика () государство, расположенное в северной части Европы. Столица страны Вильнюс.
Площадь км². Протяжённость с севера на юг 280 км, а с запада на восток 370 км. Население составляет человек (сентябрь, 2019). Занимает 140-е место место в мире по численности населения и 121-е по территории. Имеет выход к Балтийскому морю, расположена на его восточном побережье. Береговая линия составляет всего 99 км (наименьший показатель среди государств Балтии). На севере граничит с Латвией, на юго-востоке с Белоруссией, на юго-западе с Польшей и Калининградской областью России.
Член ООН с 1991 года, ЕС и НАТО с 2004 года, ОЭСР с мая 2018 года. Входит в Шенгенскую зону и Еврозону.
Независимость страны провозглашена 11 марта 1990 года, а юридически оформлена 6 сентября 1991 года. .
Этимология слова «Литва» точно не известна, при этом существует множество версий, ни одна из которых не получила всеобщего признания. Корень «лит» и его варианты «лет»/«лют» допускают различные толкования как в балтских и славянских, так и в других индоевропейских языках. Так, например, существуют созвучные топонимы на территории Словакии «"Lytva"» и Румынии «"Litua"», известные с XIXII веков. По мнению Е. Поспелова, топоним образован от древнего названия реки Летава (Lietavà от «лить», русское «Летаука»). Феодальное княжество, по землям которого протекала эта река, со временем заняло ведущее положение и название было распространено на всё государство. В «Повести временных лет» (XII век) упоминается этноним «литва», полностью совпадающий с названием местности «Литва» и по смыслу (территория, где живёт литва), и по форме.
Поверхность  равнинная со следами древнего оледенения. Поля и луга занимают 57 % территории, леса и кустарники  30 %, болота  6 %, внутренние воды  1 %.
Высшая точка  293,84 м над уровнем моря  холм Аукштояс (или Аукштасис калнас) в юго-восточной части страны, в 23,5 км от Вильнюса.
Крупнейшие реки  Неман и Вилия.
Более 3 тыс. озёр (1,5 % территории): крупнейшее из них  Друкшяй на границе Латвии, Литвы и Белоруссии (площадь 44,8 км²), самое глубокое  Таурагнас, 61 м), самое длинное  Асвея длинной в 30 км у местечка Дубингяй.
Климат переходный от морского к континентальному. Средняя температура зимой 5 °C, летом +17 °C. Выпадает 748 мм осадков в год.
Полезные ископаемые: торф, минеральные материалы, строительные материалы.
Территория современной Литвы была заселена людьми с конца XIX тысячелетия до н. э. Жители занимались охотой и рыболовством, использовали лук и стрелы с кремнёвыми наконечниками, скребки для обработки кожи, удочки и сети. В конце неолита (IIIII тысячелетия до н. э.) на территорию современной Литвы проникли индоевропейские племена. Они занимались земледелием и скотоводством, при этом охота и рыболовство оставались основными занятиями местных жителей вплоть до широкого распространения железных орудий труда. Индоевропейцы, заселившие земли между устьями Вислы и Западной Двины, выделились в отдельную группу, названную учёными балтами.
Традиционно считается, что этническая основа Литвы сформирована носителями археологической культуры восточнолитовских курганов, сложившейся в V веке н. э. на территории современных Восточной Литвы и Северо-Западной Белоруссии. Около VII века литовский язык отделился от латышского.
Становление государственности на территории современной Литвы относят к XIII веку, при этом само название «Литва» впервые упомянуто в Кведлинбургских анналах под 1009 годом в сообщении об убийстве язычниками миссионера Бруно на границе Руси и Литвы. По наиболее распространённой версии, топоним возник от названия небольшой реки Летаука, притока Няриса. Согласно более современной гипотезе, название страны могло произойти от этнонима «леты» или «лейти», которым жители окрестных земель называли дружинников литовских князей.
В начале XIII века в земли балтов-язычников с запада началось вторжение немецких рыцарей-крестоносцев. Они покорили Пруссию и Ливонию. В это же время с юга началась экспансия Галицко-Волынского княжества. К середине XIII века многие литовские земли были объединены под властью князя Миндовга, принявшего в 1251 году католическое крещение и коронованного в 1253 году. Через несколько лет Миндовг отрёкся от христианства и до начала XIV века литовские земли оставались языческими. Несмотря на то, что уже в 1263 году Миндовг был свергнут, его правление положило начало более чем пятисотлетнему существованию Великого княжества Литовского.
В XIV  начале XV веках территория Великого княжества Литовского стремительно росла, в основном за счёт присоединения земель Западной Руси. Включение в состав государства славянских земель, многократно превышающих по площади и количеству населения собственно литовские земли, привело к перениманию литовскими князьями, получившими во владение русские земли, православной культуры и западнорусского языка. Со временем западнорусский язык стал официальным языком канцелярии великих князей. Собственно литовский язык до XVI века оставался бесписьменным, хотя и продолжал использоваться на этнически литовских землях.
В 1385 году великий князь литовский Ягайло заключил Кревскую унию с Королевством Польским. По условиям унии, Ягайло обязался присоединить Великое княжество Литовское к Королевству Польскому и крестить литовские земли по католическому обряду, а сам становился королём Польши и сохранял титул великого князя литовского. Однако вскоре он вынужден был уступить власть в Великом княжестве Литовском своему двоюродному брату Витовту.''';
@@ -1,48 +0,0 @@
// This text is an extract from the Slovak Wikipedia article about Esperanto:
// https://sk.wikipedia.org/wiki/Esperanto
//
// The extract is based on the Wikipedia database dump. All markup has been
// removed using WikiExtractor: https://github.com/attardi/wikiextractor
//
// The material is licensed under the Creative Commons Attribution-Share-Alike
// License 3.0: https://creativecommons.org/licenses/by-sa/3.0/
// @dart=2.9
const String sk = '''
Esperanto (pôvodne Lingvo Internacia medzinárodný jazyk) je najrozšírenejší medzinárodný plánový jazyk. Názov je odvodený od pseudonymu, pod ktorým v roku 1887 zverejnil lekár L. L. Zamenhof základy tohto jazyka. Zámerom tvorcu bolo vytvoriť ľahko naučiteľný a použiteľný neutrálny jazyk, vhodný na použitie v medzinárodnej komunikácii. Cieľom nebolo nahradiť národné jazyky, čo bolo neskôr aj deklarované v Boulonskej deklarácii.
Hoci žiaden štát neprijal esperanto ako úradný jazyk, používa ho komunita s odhadovaným počtom hovoriacich 100 000 2 000 000, z čoho približne 2 000 tvoria rodení hovoriaci. V Poľsku je na zozname nemateriálneho kultúrneho dedičstva. Získalo aj isté medzinárodné uznania, napríklad dve rezolúcie UNESCO či podporu známych osobností verejného života. V súčasnosti sa esperanto využíva pri cestovaní, korešpondencii, medzinárodných stretnutiach a kultúrnych výmenách, kongresoch, vedeckých diskusiách, v pôvodnej aj prekladovej literatúre, divadle a kine, hudbe, tlačenom aj internetovom spravodajstve, rozhlasovom a televíznom vysielaní.
Slovná zásoba esperanta pochádza predovšetkým zo západoeurópskych jazykov, zatiaľ čo jeho skladba a tvaroslovie ukazujú na silný slovanský vplyv. Morfémy nemenné a je možné ich kombinovať takmer bez obmedzení do rozmanitých slov; esperanto teda mnoho spoločného s analytickými jazykmi, ako je čínština, zatiaľ čo vnútorná stavba jeho slov pripomína jazyky aglutinačné, ako je japončina, swahilčina alebo turečtina.
Pri zrode esperanta stál Ludwik Lejzer Zamenhof. Vyrastal v mnohojazyčnom, vtedy ruskom, teraz poľskom meste Białystok, kde bol svedkom častých sporov medzi jednotlivými národnosťami (Rusi, Poliaci, Nemci, Židia). Pretože za jednu z hlavných príčin týchto sporov považoval neexistenciu spoločného jazyka, začal ako školák pracovať na projekte reči, ktorá by túto funkciu mohla plniť. Mala byť, na rozdiel od národných jazykov, neutrálna a ľahko naučiteľná, teda prijateľná ako druhý jazyk pre všetkých, jazyk vyučovaný spoločne s národnými jazykmi a používaný v situáciách vyžadujúcich dorozumenie medzi národmi.
Zamenhof najskôr uvažoval o oživení latinčiny, ktorú sa učil v škole, ale usúdil, že je pre bežné dorozumievanie zbytočne zložitá. Keď študoval angličtinu, všimol si, že časovanie slovies podľa osoby a čísla nie je nutné; že gramatický systém jazyka môže byť oveľa jednoduchší, než sa dovtedy nazdával. Stále však zostávala prekážka v memorovaní sa veľkého množstva slov. Raz Zamenhofa zaujali dva ruské nápisy: "швейцарская" [švejcarskaja] (vrátnica, odvodené od "швейцар" [švejcar] vrátnik) a "кондитерская" [konditerskaja] (cukráreň, odvodené od "кондитер" [konditér] cukrár). Tieto slová rovnakého zakončenia mu vnukli myšlienku, že používanie pravidelných predpôn a prípon by mohlo významne znížiť množstvo slovných koreňov nutných na dorozumenie sa. Aby boli korene čo najmedzinárodnejšie, rozhodol sa prevziať slovnú zásobu predovšetkým z románskych a germánskych jazykov, teda tých, ktoré boli vtedy v školách po celom svete vyučované najčastejšie.
Prvý Zamenhofov projekt, nazvaný "Lingwe uniwersala," bol viac-menej hotový v roku 1878, ale autorov otec, učiteľ jazykov, považoval túto prácu za márnu a utopistickú, a zrejme preto rukopis, ktorý mu bol zverený, zničil. V rokoch 1879  1885 Zamenhof študoval medicínu v Moskve a vo Varšave. V tej dobe začal znova pracovať na medzinárodnom jazyku. Prvú obnovenú verziu vyučoval v roku 1879 pre svojich priateľov. Po niekoľkých rokoch prekladal poéziu, aby jazyk čo najviac zdokonalil. V roku 1885 autor napísal:
Zamenhofovi prichádzalo veľa nadšených listov, ktoré často prinášali najrôznejšie návrhy úprav jazyka. Všetky podnety zaznamenával a neskoršie ich začal uverejňovať v časopise "Esperantisto", vychádzajúcom v Norimbergu. V tom istom časopise aj dal o úpravách dvakrát hlasovať, väčšina čitateľov však so zmenami nesúhlasila. Po týchto hlasovaniach na určitý čas utíchli hlasy volajúce po reforme a jazyk sa začal rozširovať. Najviac odberateľov mal časopis vo vtedajšom Rusku. Veľkou ranou preň bolo, keď ruská cenzúra jeho šírenie zakázala kvôli článku Leva Nikolajeviča Tolstého. Časopis kvôli tomu musel byť zrušený, krátko na to bol však vystriedaný novým, nazvaným "Lingvo Internacia." Najskôr ho redigovali vo švédskej Uppsale, neskôr v Maďarsku a nakoniec v Paríži, kde jeho vydávanie zastavila prvá svetová vojna.
Nový medzinárodný jazyk začali jeho používatelia skoro používať aj na organizáciu odbornej a záujmovej činnosti na medzinárodnej úrovni. V prvých desaťročiach prebiehala komunikácia v esperante takmer výhradne písomnou formou. Ale po nečakane úspešnom prvom Svetovom kongrese esperanta, usporiadanom v roku 1905 vo francúzskom meste Boulogne-sur-Mer, na ktorom sa overili možnosti používania tejto reči v hovorenej forme, začali naberať na intenzite aj osobné kontakty.
Esperanto začali pre svoju činnosť používať aj rôzne organizácie a hnutia. na svetovom kongrese v Barcelone roku 1909 sa uskutočnilo niekoľko stretnutí prítomných katolíkov, ktorí sa nakoniec rozhodli usporiadať v nadchádzajúcom roku, 1910, samostatný kongres katolíckych esperantistov. Počas neho bolo založené Medzinárodné združenie katolíckych esperantistov (IKUE Internacia Katolika Unuiĝo Esperantista). Časopis "Espero Katolika" ("Katolícka nádej") vychádzal od roku 1903 a s viac ako 100 rokmi svojej existencie je dnes najdlhšie vychádzajúcim esperantským periodikom.
V roku 1912 sa Zamenhof pri slávnostnom prejave ôsmeho Svetového kongresu esperanta v Krakove vzdal svojej oficiálnej úlohy v hnutí. Desiaty kongres sa mal konať v roku 1914 v Paríži, prihlásilo sa naň takmer 4 000 ľudí, ale nakoniec ho zrušili pre začínajúcu vojnu, Zamenhof sa vtedy musel vrátiť domov cez škandinávske štáty.
Po vojne túžba po harmónii a mieri vzbudila nové nádeje, vďaka čomu sa esperanto veľmi rýchlo šírilo. Prvý povojnový kongres sa konal v roku 1920 v Haagu, 13. svetový kongres v 1921 v Prahe. V roku 1927 bolo vo viedenskom Hofburgu otvorené Medzinárodné esperantské múzeum, v roku 1929 bolo pripojené k Rakúskej národnej knižnici a dnes sídli v samostatnej budove.
Snahy o presadenie esperanta ako univerzálneho jazyka sa stretávali s pozitívnou odozvou: Petíciu v jeho prospech adresovanú Organizácii Spojených národov podpísalo vyše 80 miliónov ľudí, v Česko-Slovensku napríklad prof. Jaroslav Heyrovský, nositeľ Nobelovej ceny.
Valné zhromaždenie UNESCO prijalo podobné rezolúcie v Montevideu 10. decembra 1954 a v Sofii 8. novembra 1985. Vzalo v nich na vedomie "výsledky dosiahnuté esperantom na poli medzinárodnej duchovnej výmeny aj zblíženia národov sveta" a vyzvalo členské štáty, "aby sa chopili iniciatívy pri zavádzaní študijných programov o jazykovom probléme a esperante na svojich školách a inštitúciách vyššieho vzdelávania".
K esperantu sa hlásila aj rada predsedov Poľskej akadémie vied. Jubilejného 72. Svetového kongresu esperanta roku 1987 (100. výročie uverejnenia prvej učebnice jazyka) sa vo Varšave zúčastnilo takmer 6 000 ľudí zo 60 národov.
Pokroky dosiahli aj katolícki esperantisti roku 1990 bol vydaný dokument "Norme per la celebrazione della Messa in esperanto", ktorým Svätá stolica povoľuje vysluhovať sväté omše v tomto jazyku bez zvláštneho povolenia. Esperanto sa tak stalo jediným schváleným umelým liturgickým jazykom katolíckej cirkvi.
Skutočnosť, že mnohé z cieľov esperantského hnutia sa doteraz nepodarilo naplniť, je často prisudzovaná okrem iného technologickej a kultúrnej dominancii Spojeného kráľovstva a Spojených štátov amerických, predovšetkým v období po druhej svetovej vojne, vďaka čomu je v súčasnosti dorozumievacím jazykom väčšiny medzinárodných činností angličtina.
na začiatku 20. storočia bolo na území dnešného Slovenska (vtedy severná časť Uhorska) činné esperantské hnutie. Esperantistov a kluby zastrešovala Uhorská esperantská spoločnosť a Verda Standardo. V Prahe boli činné spolky "Bohema Unio Esperantista", ktorý prijímal len organizácie a kluby, a "Bohema Asocio Esperantista", ktorý prijímal jednotlivcov. Oba spolky vydávali svoje časopisy. V roku 1907, 20 rokov po zverejnení jazyka Zamenhofom, vydal tolstojovec Albert Škarvan spolu s Rusom N. P. Evstifejevom prvú učebnicu esperanta v slovenčine, Základy medzinárodnej reči ESPERANTO.
Po prvej svetovej vojne sa oba pražské spolky zlúčili do "Československej Esperantskej Asociácie". bola v roku 1936 premenovaná na "Esperantskú Asociáciu v Československej republike". V tomto období bolo hnutie veľmi aktívne, fungovalo mnoho klubov, konalo sa veľa prednášok a kurzov. Esperanto bolo vyučované na školách rôznych stupňov, rádio Bratislava od 1930 vysielalo kurzy a od 1932 aj kultúrny program v esperante. Bola vydaná "Československá antológia" predstavujúca diela 20 slovenských autorov. V rámci protifašistickej aktivity vychádzali aj preklady protifašistických článkov z esperantských časopisov z obdobia Španielskej občianskej vojny.
Druhá svetová vojna utlmila esperantské hnutie. Bratislavský esperantský klub požiadal o zmenu štatútu a rozšírenie poľa pôsobnosti na celú vtedajšiu Slovenskú republiku a následne sa stal strediskom esperantského hnutia na Slovensku.''';
@@ -1,75 +0,0 @@
// This text is an extract from the Chinese Wikipedia article about Kanji
// (): https://zh.wikipedia.org/wiki/
//
// The extract is based on the Wikipedia database dump. All markup has been
// removed using WikiExtractor: https://github.com/attardi/wikiextractor
//
// The material is licensed under the Creative Commons Attribution-Share-Alike
// License 3.0: https://creativecommons.org/licenses/by-sa/3.0/
// @dart=2.9
const String zh = '''
丿𠄌𠃋𠃉𠃊
5471-{}-6464-{}-𠔻52
TRON计划中使3-{}-3-{}-84C区JMK66147C区的时间原因被安排到了扩展D区G区并被接受
西Unicode中它們都是獨立區塊編碼的
Unicode中與漢字一道編入漢字區
Unicode中作為獨立區塊編碼
滿
使
滿
使使使使使使
3使使-{}--{}--{}--{}--{}--{}-
3使-l
1443使使2011使1948
1便使便
1945使
使
西
使
-{}--{}-
使-{}--{}--{}--{}--{}--{}-
1956-{}--{}-1988-{}--{}--{}--{}--{}--{}-
26
OCR广
GB 2312B''';
-2
View File
@@ -3,8 +3,6 @@
# BSD-style license that can be found in the LICENSE file.
analyzer:
exclude:
- '*/dart2/' # These don't analyze cleanly on newer sdks
# strong-mode:
# implicit-casts: false
linter: