Last active
January 15, 2025 07:30
-
-
Save PlugFox/88ba6027a341fd02d94c58e80123cf05 to your computer and use it in GitHub Desktop.
Dart: Nums benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:isolate'; | |
import 'dart:math' as math; | |
import 'dart:typed_data'; | |
import 'package:benchmark_harness/benchmark_harness.dart'; | |
// $ dart run bin/nums.dart | |
// | |
// $ dart compile exe bin/nums.dart -o out/nums.exe | |
// $ ./out/nums.exe | |
void main() => Future<void>(() async { | |
const length = 10000; | |
final pairs = [ | |
(List<int>.filled(length, 0), List<int>.filled(length, 0)), | |
(List<int>.filled(length, 0), List<double>.filled(length, .0)), | |
(List<double>.filled(length, .0), List<int>.filled(length, 0)), | |
(List<double>.filled(length, 0), List<double>.filled(length, .0)), | |
(Uint32List(length), Uint32List(length)), | |
(Int32List(length), Int32List(length)), | |
(Float64List(length), Float64List(length)), | |
(Float32List(length), Float32List(length)), | |
]; | |
final randomData = List<int>.generate( | |
length, | |
(index) => math.Random().nextInt(1000) + 1, | |
growable: false, | |
); | |
List<T> fill<T extends num>(List<T> list) { | |
if (list is List<int>) { | |
for (var i = 0; i < list.length; i++) list[i] = randomData[i] as T; | |
} else if (list is List<double>) { | |
for (var i = 0; i < list.length; i++) | |
list[i] = randomData[i].toDouble() as T; | |
} else { | |
throw ArgumentError('Unsupported type: $T for ${list.runtimeType}'); | |
} | |
return list; | |
} | |
for (var (a, b) in pairs) { | |
fill(a); | |
fill(b); | |
} | |
Future<List<String>> Function() process( | |
NumBenchmark<A, B> Function<A extends num, B extends num>( | |
List<A> a, | |
List<B> b, | |
) fn, | |
) { | |
final benchmarks = pairs.map((pair) => fn(pair.$1, pair.$2)); | |
Future<(String, double)> compute(BenchmarkBase benchmark) => | |
Isolate.run(() => benchmark.measure()) | |
.then((result) => (benchmark.name, result)); | |
return () async { | |
/* final results = await Future.wait<(String, double)>( | |
benchmarks.map<Future<(String, double)>>(compute), | |
); */ | |
final results = await Stream.fromFutures( | |
benchmarks.map<Future<(String, double)>>(compute), | |
).toList(); | |
results..sort((a, b) => a.$2.compareTo(b.$2)); | |
return results | |
.map((pair) => '${pair.$1}: ${pair.$2.toStringAsFixed(2)} us') | |
.toList(growable: false); | |
}; | |
} | |
// Summation | |
final buffer = StringBuffer() | |
..writeln('#' * 16) | |
..writeln('# Summation') | |
..writeln('#' * 16); | |
final sum = await process(SumBenchmark.new)(); | |
buffer.writeln(sum.join('\n')); | |
buffer | |
..writeln() | |
..writeln(); | |
// Multiplication | |
buffer | |
..writeln('#' * 16) | |
..writeln('# Multiplication') | |
..writeln('#' * 16); | |
final mul = await process(MulBenchmark.new)(); | |
buffer.writeln(mul.join('\n')); | |
buffer | |
..writeln() | |
..writeln(); | |
// Division | |
buffer | |
..writeln('#' * 16) | |
..writeln('# Division') | |
..writeln('#' * 16); | |
final div = await process(DivBenchmark.new)(); | |
buffer.writeln(div.join('\n')); | |
print(buffer.toString()); | |
}); | |
abstract interface class NumBenchmark<A extends num, B extends num> | |
implements BenchmarkBase {} | |
class SumBenchmark<A extends num, B extends num> extends BenchmarkBase | |
implements NumBenchmark<A, B> { | |
SumBenchmark(List<A> a, List<B> b) | |
: _a = a, | |
_b = b, | |
_c = List.filled(math.max(a.length, b.length), 0, growable: false), | |
assert(a.length == b.length, 'a and b must have the same length'), | |
super('${a.runtimeType} + ${b.runtimeType}'); | |
final List<A> _a; | |
final List<B> _b; | |
final List<num> _c; | |
@override | |
void run() { | |
for (var i = 0; i < _a.length; i++) _c[i] = _a[i] + _b[i]; | |
} | |
@override | |
void teardown() { | |
if (_c.length != _a.length) throw StateError('c.length != a.length'); | |
for (var i = 0; i < _c.length; i++) | |
if (_c[i] != _a[i] + _b[i]) | |
throw StateError('c[$i] != a[$i] + b[$i]\n' | |
'${_c[i]} != ${_a[i]} + ${_b[i]} != ${_a[i] + _b[i]}'); | |
super.teardown(); | |
} | |
} | |
class MulBenchmark<A extends num, B extends num> extends BenchmarkBase | |
implements NumBenchmark<A, B> { | |
MulBenchmark(List<A> a, List<B> b) | |
: _a = a, | |
_b = b, | |
_c = List.filled(math.max(a.length, b.length), 0, growable: false), | |
assert(a.length == b.length, 'a and b must have the same length'), | |
super('${a.runtimeType} * ${b.runtimeType}'); | |
final List<A> _a; | |
final List<B> _b; | |
final List<num> _c; | |
@override | |
void run() { | |
for (var i = 0; i < _a.length; i++) _c[i] = _a[i] * _b[i]; | |
} | |
@override | |
void teardown() { | |
if (_c.length != _a.length) throw StateError('c.length != a.length'); | |
for (var i = 0; i < _c.length; i++) | |
if (_c[i] != _a[i] * _b[i]) | |
throw StateError('c[$i] != a[$i] * b[$i]\n' | |
'${_c[i]} != ${_a[i]} * ${_b[i]} != ${_a[i] * _b[i]}'); | |
super.teardown(); | |
} | |
} | |
class DivBenchmark<A extends num, B extends num> extends BenchmarkBase | |
implements NumBenchmark<A, B> { | |
DivBenchmark(List<A> a, List<B> b) | |
: _a = a, | |
_b = b, | |
_c = List.filled(math.max(a.length, b.length), 0, growable: false), | |
assert(a.length == b.length, 'a and b must have the same length'), | |
super('${a.runtimeType} / ${b.runtimeType}'); | |
final List<A> _a; | |
final List<B> _b; | |
final List<num> _c; | |
@override | |
void run() { | |
for (var i = 0; i < _a.length; i++) _c[i] = _a[i] / _b[i]; | |
} | |
@override | |
void teardown() { | |
if (_c.length != _a.length) throw StateError('c.length != a.length'); | |
for (var i = 0; i < _c.length; i++) | |
if (_c[i] != _a[i] / _b[i]) | |
throw StateError('c[$i] != a[$i] / b[$i]\n' | |
'${_c[i]} != ${_a[i]} / ${_b[i]} != ${_a[i] / _b[i]}'); | |
super.teardown(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment