e4c8b49dcc
Change-Id: I1362ada67a02b0ed352612fc29c727e94d8cd254 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/394901 Commit-Queue: Daco Harkes <dacoharkes@google.com> Auto-Submit: Bob Nystrom <rnystrom@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com>
326 lines
6.2 KiB
Dart
326 lines
6.2 KiB
Dart
// 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.
|
|
|
|
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.new,
|
|
Int64x20.new,
|
|
Doublex01.new,
|
|
Doublex20.new,
|
|
Handlex01.new,
|
|
Handlex20.new,
|
|
];
|
|
for (final benchmark in benchmarks) {
|
|
benchmark().report();
|
|
}
|
|
}
|