[dart2wasm] Add more JS interop benchmarks
In prep for [1], benchmark `dartify` performance when converting JS call
return values to Dart values.
[1]: https://dart-review.googlesource.com/c/sdk/+/424021
Change-Id: I43549276f0ccdfefcc689c0574f82cad4a856aa5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/424940
Commit-Queue: Ömer Ağacan <omersa@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
diff --git a/benchmarks/WasmJSInterop/WasmJSInterop.dart b/benchmarks/WasmJSInterop/WasmJSInterop.dart
index 33d50cf..205a911 100644
--- a/benchmarks/WasmJSInterop/WasmJSInterop.dart
+++ b/benchmarks/WasmJSInterop/WasmJSInterop.dart
@@ -65,10 +65,213 @@
calls;
}
+@JS()
+external bool dartifyBool();
+
+@JS()
+external bool? dartifyNullableBool();
+
+@JS()
+external num dartifyNum();
+
+@JS()
+external num? dartifyNullableNum();
+
+@JS()
+external double dartifyDouble();
+
+@JS()
+external double? dartifyNullableDouble();
+
+@JS()
+external int dartifyInt();
+
+@JS()
+external int? dartifyNullableInt();
+
+@JS()
+external String dartifyString();
+
+@JS()
+external String? dartifyNullableString();
+
+@JS()
+external JSArray dartifyJSArray();
+
+@JS()
+external JSArray? dartifyNullableJSArray();
+
+// `dart:typed_data` types are all boxed the same way, so no need to test each
+// one of them separately.
+@JS()
+external JSUint8Array dartifyJSUint8Array();
+
+@JS()
+external JSUint8Array? dartifyNullableJSUint8Array();
+
+const int ITERATIONS = 10000;
+
+bool boolSink = false;
+
+double dartifyBoolBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ boolSink = dartifyBool();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+bool? nullableBoolSink = null;
+
+double dartifyNullableBoolBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ nullableBoolSink = dartifyNullableBool();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+num numSink = 1;
+
+double dartifyNumBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ numSink = dartifyNum();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+num? nullableNumSink = null;
+
+double dartifyNullableNumBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ nullableNumSink = dartifyNullableNum();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+double doubleSink = 0.0;
+
+double dartifyDoubleBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ doubleSink = dartifyDouble();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+double? nullableDoubleSink = null;
+
+double dartifyNullableDoubleBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ nullableDoubleSink = dartifyNullableDouble();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+int intSink = 0;
+
+double dartifyIntBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ intSink = dartifyInt();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+int? nullableIntSink = null;
+
+double dartifyNullableIntBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ nullableIntSink = dartifyNullableInt();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+String stringSink = "";
+
+double dartifyStringBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ stringSink = dartifyString();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+String? nullableStringSink = null;
+
+double dartifyNullableStringBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ nullableStringSink = dartifyNullableString();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+JSArray jsArraySink = JSArray();
+
+double dartifyJSArrayBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ jsArraySink = dartifyJSArray();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+JSArray? nullableJsArraySink = null;
+
+double dartifyNullableJSArrayBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ nullableJsArraySink = dartifyNullableJSArray();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+JSUint8Array jsUint8ArraySink = JSUint8Array();
+
+double dartifyJSUint8ArrayBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ jsUint8ArraySink = dartifyJSUint8Array();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
+JSUint8Array? nullableJsUint8ArraySink = null;
+
+double dartifyNullableJSUint8ArrayBenchmark() =>
+ BenchmarkBase.measureFor(() {
+ for (int i = 0; i < ITERATIONS; i += 1) {
+ nullableJsUint8ArraySink = dartifyNullableJSUint8Array();
+ }
+ }, minimumMeasureDurationMillis) /
+ ITERATIONS;
+
void main() {
eval('''
self.intFun = (i) => i;
self.doubleFun = (d) => d;
+ self.dartifyBool = () => true;
+ self.dartifyNullableBool = () => false;
+ self.dartifyNum = () => 12.34;
+ self.dartifyNullableNum = () => 56.78;
+ self.dartifyDouble = () => 10.20;
+ self.dartifyNullableDouble = () => 30.40;
+ self.dartifyInt = () => 123;
+ self.dartifyNullableInt = () => 456;
+ self.dartifyString = () => "abc";
+ self.dartifyNullableString = () => "def";
+
+ // Arrays are all empty to not add element conversion overheads to the
+ // benchmark results.
+ self.dartifyJSArray = () => new Array();
+ self.dartifyNullableJSArray = () => new Array();
+ self.dartifyJSUint8Array = () => new Uint8Array(0);
+ self.dartifyNullableJSUint8Array = () => new Uint8Array(0);
''');
final maxI31 = (1 << 30) - 1;
@@ -84,6 +287,57 @@
DoublePassingBenchmark(1.0, 1.0, 10).measure();
final double = DoublePassingBenchmark(1.0, 12.34, 1000000).measure();
report('WasmJSInterop.call.void.1ArgsDouble', double);
+
+ report('WasmJSInterop.call.bool.0Args', dartifyBoolBenchmark());
+ report(
+ 'WasmJSInterop.call.nullableBool.0Args',
+ dartifyNullableBoolBenchmark(),
+ );
+ report('WasmJSInterop.call.num.0Args', dartifyNumBenchmark());
+ report('WasmJSInterop.call.nullableNum.0Args', dartifyNullableNumBenchmark());
+ report('WasmJSInterop.call.double.0Args', dartifyDoubleBenchmark());
+ report(
+ 'WasmJSInterop.call.nullableDouble.0Args',
+ dartifyNullableDoubleBenchmark(),
+ );
+ report('WasmJSInterop.call.int.0Args', dartifyIntBenchmark());
+ report('WasmJSInterop.call.nullableInt.0Args', dartifyNullableIntBenchmark());
+ report('WasmJSInterop.call.string.0Args', dartifyStringBenchmark());
+ report(
+ 'WasmJSInterop.call.nullableString.0Args',
+ dartifyNullableStringBenchmark(),
+ );
+ report('WasmJSInterop.call.JSArray.0Args', dartifyJSArrayBenchmark());
+ report(
+ 'WasmJSInterop.call.nullableJSArray.0Args',
+ dartifyNullableJSArrayBenchmark(),
+ );
+ report(
+ 'WasmJSInterop.call.JSUint8Array.0Args',
+ dartifyJSUint8ArrayBenchmark(),
+ );
+ report(
+ 'WasmJSInterop.call.nullableJSUint8Array.0Args',
+ dartifyNullableJSUint8ArrayBenchmark(),
+ );
+
+ // To keep the sinks alive
+ if (int.parse('1') == 0) {
+ print(boolSink);
+ print(nullableBoolSink);
+ print(numSink);
+ print(nullableNumSink);
+ print(doubleSink);
+ print(nullableDoubleSink);
+ print(intSink);
+ print(nullableIntSink);
+ print(stringSink);
+ print(nullableStringSink);
+ print(jsArraySink);
+ print(nullableJsArraySink);
+ print(jsUint8ArraySink);
+ print(nullableJsUint8ArraySink);
+ }
}
/// Reports in Golem-specific format.