4c20cedd30
Now that I'm able to open the entire SDK in VSC, I'm fixing some of the analysis issues in various files (carefully) without changing their meaning. In this case, I removed unnecessary imports from benchmarks. In regexp_benchmark I ignored one warning which likely would have changed the behavior of the code. BUG=https://github.com/dart-lang/sdk/issues/52419 Change-Id: I9a195a4e45121313bd9f065f2579a165c3fec05b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/303901 Auto-Submit: Eric Seidel <eric@shorebird.dev> Reviewed-by: William Hesse <whesse@google.com> Commit-Queue: William Hesse <whesse@google.com>
278 lines
6.0 KiB
Dart
278 lines
6.0 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();
|
|
}
|
|
}
|