blob: e6c922e62918d69d73e8aa550e235c9deccaaa0b [file] [log] [blame]
// 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.
// TODO(37581): Generate this file.
// These micro benchmarks track the speed of reading and writing C memory from
// Dart with a specific marshalling and unmarshalling of data.
import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
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.
DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific('native_functions',
path: Platform.script.resolve('../native/out/').path);
//
// Native types and their Dart counterparts.
//
typedef NativeFunction1Uint8 = Uint8 Function(Uint8);
typedef NativeFunction1Uint16 = Uint16 Function(Uint16);
typedef NativeFunction1Uint32 = Uint32 Function(Uint32);
typedef NativeFunction1Uint64 = Uint64 Function(Uint64);
typedef NativeFunction1Int8 = Int8 Function(Int8);
typedef NativeFunction1Int16 = Int16 Function(Int16);
typedef NativeFunction1Int32 = Int32 Function(Int32);
typedef NativeFunction1Int64 = Int64 Function(Int64);
typedef Function1int = int Function(int);
typedef NativeFunction2Int32 = Int32 Function(Int32, Int32);
typedef NativeFunction2Int64 = Int64 Function(Int64, Int64);
typedef Function2int = int Function(int, int);
typedef NativeFunction4Int32 = Int32 Function(Int32, Int32, Int32, Int32);
typedef NativeFunction4Int64 = Int64 Function(Int64, Int64, Int64, Int64);
typedef Function4int = int Function(int, int, int, int);
typedef NativeFunction10Int32 = Int32 Function(
Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32);
typedef NativeFunction10Int64 = Int64 Function(
Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64);
typedef Function10int = int Function(
int, int, int, int, int, int, int, int, int, int);
typedef NativeFunction20Int32 = Int32 Function(
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32,
Int32);
typedef NativeFunction20Int64 = Int64 Function(
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64,
Int64);
typedef Function20int = int Function(int, int, int, int, int, int, int, int,
int, int, int, int, int, int, int, int, int, int, int, int);
typedef NativeFunction1Float = Float Function(Float);
typedef NativeFunction1Double = Double Function(Double);
typedef Function1double = double Function(double);
typedef NativeFunction2Float = Float Function(Float, Float);
typedef NativeFunction2Double = Double Function(Double, Double);
typedef Function2double = double Function(double, double);
typedef NativeFunction4Float = Float Function(Float, Float, Float, Float);
typedef NativeFunction4Double = Double Function(Double, Double, Double, Double);
typedef Function4double = double Function(double, double, double, double);
typedef NativeFunction10Float = Float Function(
Float, Float, Float, Float, Float, Float, Float, Float, Float, Float);
typedef NativeFunction10Double = Double Function(Double, Double, Double, Double,
Double, Double, Double, Double, Double, Double);
typedef Function10double = double Function(double, double, double, double,
double, double, double, double, double, double);
typedef NativeFunction20Float = Float Function(
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float,
Float);
typedef NativeFunction20Double = Double Function(
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double,
Double);
typedef Function20double = double Function(
double,
double,
double,
double,
double,
double,
double,
double,
double,
double,
double,
double,
double,
double,
double,
double,
double,
double,
double,
double);
typedef Function1PointerUint8 = Pointer<Uint8> Function(Pointer<Uint8>);
typedef Function2PointerUint8 = Pointer<Uint8> Function(
Pointer<Uint8>, Pointer<Uint8>);
typedef Function4PointerUint8 = Pointer<Uint8> Function(
Pointer<Uint8>, Pointer<Uint8>, Pointer<Uint8>, Pointer<Uint8>);
typedef Function10PointerUint8 = Pointer<Uint8> Function(
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>);
typedef Function20PointerUint8 = Pointer<Uint8> Function(
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>,
Pointer<Uint8>);
typedef NativeFunction1Handle = Handle Function(Handle);
typedef Function1Object = Object Function(Object);
typedef NativeFunction2Handle = Handle Function(Handle, Handle);
typedef Function2Object = Object Function(Object, Object);
typedef NativeFunction4Handle = Handle Function(Handle, Handle, Handle, Handle);
typedef Function4Object = Object Function(Object, Object, Object, Object);
typedef NativeFunction10Handle = Handle Function(Handle, Handle, Handle, Handle,
Handle, Handle, Handle, Handle, Handle, Handle);
typedef Function10Object = Object Function(Object, Object, Object, Object,
Object, Object, Object, Object, Object, Object);
typedef NativeFunction20Handle = Handle Function(
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle);
typedef Function20Object = Object Function(
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object);
//
// Benchmark fixtures.
//
abstract class FfiBenchmarkBase extends BenchmarkBase {
final bool isLeaf;
FfiBenchmarkBase(String name, {this.isLeaf: false})
: super('$name${isLeaf ? 'Leaf' : ''}');
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 FfiBenchmarkBase {
final Function1int f;
Uint8x01({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction1Uint8,
Function1int>('Function1Uint8', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction1Uint8,
Function1int>('Function1Uint8', isLeaf: false),
super('FfiCall.Uint8x01', isLeaf: isLeaf);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(17);
}
expectEquals(x, N * 17 + N * 42);
}
}
class Uint16x01 extends FfiBenchmarkBase {
final Function1int f;
Uint16x01({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction1Uint16,
Function1int>('Function1Uint16', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction1Uint16,
Function1int>('Function1Uint16', isLeaf: false),
super('FfiCall.Uint16x01', isLeaf: isLeaf);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(17);
}
expectEquals(x, N * (17 + 42));
}
}
class Uint32x01 extends FfiBenchmarkBase {
final Function1int f;
Uint32x01({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction1Uint32,
Function1int>('Function1Uint32', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction1Uint32,
Function1int>('Function1Uint32', isLeaf: false),
super('FfiCall.Uint32x01', isLeaf: isLeaf);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(i);
}
expectEquals(x, N * (N - 1) / 2 + N * 42);
}
}
class Uint64x01 extends FfiBenchmarkBase {
final Function1int f;
Uint64x01({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction1Uint64,
Function1int>('Function1Uint64', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction1Uint64,
Function1int>('Function1Uint64', isLeaf: false),
super('FfiCall.Uint64x01', isLeaf: isLeaf);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(i);
}
expectEquals(x, N * (N - 1) / 2 + N * 42);
}
}
class Int8x01 extends FfiBenchmarkBase {
final Function1int f;
Int8x01({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction1Int8,
Function1int>('Function1Int8', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction1Int8,
Function1int>('Function1Int8', isLeaf: false),
super('FfiCall.Int8x01', isLeaf: isLeaf);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(17);
}
expectEquals(x, N * (17 + 42));
}
}
class Int16x01 extends FfiBenchmarkBase {
final Function1int f;
Int16x01({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction1Int16,
Function1int>('Function1Int16', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction1Int16,
Function1int>('Function1Int16', isLeaf: false),
super('FfiCall.Int16x01', isLeaf: isLeaf);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(17);
}
expectEquals(x, N * (17 + 42));
}
}
class Int32x01 extends FfiBenchmarkBase {
final Function1int f;
Int32x01({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction1Int32,
Function1int>('Function1Int32', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction1Int32,
Function1int>('Function1Int32', isLeaf: false),
super('FfiCall.Int32x01', isLeaf: isLeaf);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(i);
}
expectEquals(x, N * (N - 1) / 2 + N * 42);
}
}
class Int32x02 extends FfiBenchmarkBase {
final Function2int f;
Int32x02({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction2Int32,
Function2int>('Function2Int32', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction2Int32,
Function2int>('Function2Int32', isLeaf: false),
super('FfiCall.Int32x02', isLeaf: isLeaf);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(i, i);
}
expectEquals(x, N * (N - 1) * 2 / 2);
}
}
class Int32x04 extends FfiBenchmarkBase {
final Function4int f;
Int32x04({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction4Int32,
Function4int>('Function4Int32', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction4Int32,
Function4int>('Function4Int32', isLeaf: false),
super('FfiCall.Int32x04', isLeaf: isLeaf);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(i, i, i, i);
}
expectEquals(x, N * (N - 1) * 4 / 2);
}
}
class Int32x10 extends FfiBenchmarkBase {
final Function10int f;
Int32x10({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction10Int32,
Function10int>('Function10Int32', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction10Int32,
Function10int>('Function10Int32', isLeaf: false),
super('FfiCall.Int32x10', isLeaf: isLeaf);
@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);
}
expectEquals(x, N * (N - 1) * 10 / 2);
}
}
class Int32x20 extends FfiBenchmarkBase {
final Function20int f;
Int32x20({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction20Int32,
Function20int>('Function20Int32', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction20Int32,
Function20int>('Function20Int32', isLeaf: false),
super('FfiCall.Int32x20', isLeaf: isLeaf);
@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 Int64x01 extends FfiBenchmarkBase {
final Function1int f;
Int64x01({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction1Int64,
Function1int>('Function1Int64', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction1Int64,
Function1int>('Function1Int64', isLeaf: false),
super('FfiCall.Int64x01', isLeaf: isLeaf);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(i);
}
expectEquals(x, N * (N - 1) / 2 + N * 42);
}
}
class Int64x02 extends FfiBenchmarkBase {
final Function2int f;
Int64x02({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction2Int64,
Function2int>('Function2Int64', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction2Int64,
Function2int>('Function2Int64', isLeaf: false),
super('FfiCall.Int64x02', isLeaf: isLeaf);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(i, i);
}
expectEquals(x, N * (N - 1) * 2 / 2);
}
}
class Int64x04 extends FfiBenchmarkBase {
final Function4int f;
Int64x04({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction4Int64,
Function4int>('Function4Int64', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction4Int64,
Function4int>('Function4Int64', isLeaf: false),
super('FfiCall.Int64x04', isLeaf: isLeaf);
@override
void run() {
int x = 0;
for (int i = 0; i < N; i++) {
x += f(i, i, i, i);
}
expectEquals(x, N * (N - 1) * 4 / 2);
}
}
class Int64x10 extends FfiBenchmarkBase {
final Function10int f;
Int64x10({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction10Int64,
Function10int>('Function10Int64', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction10Int64,
Function10int>('Function10Int64', isLeaf: false),
super('FfiCall.Int64x10', isLeaf: isLeaf);
@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);
}
expectEquals(x, N * (N - 1) * 10 / 2);
}
}
class Int64x20 extends FfiBenchmarkBase {
final Function20int f;
Int64x20({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction20Int64,
Function20int>('Function20Int64', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction20Int64,
Function20int>('Function20Int64', isLeaf: false),
super('FfiCall.Int64x20', isLeaf: isLeaf);
@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 Int64Mintx01 extends FfiBenchmarkBase {
final Function1int f;
Int64Mintx01({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction1Int64,
Function1int>('Function1Int64', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction1Int64,
Function1int>('Function1Int64', isLeaf: false),
super('FfiCall.Int64Mintx01', isLeaf: isLeaf);
@override
void run() {
int x = 0x7FFFFFFF00000000;
for (int i = 0; i < N; i++) {
x = f(x);
}
expectEquals(x, 0x7FFFFFFF00000000 + N * 42);
}
}
class Floatx01 extends FfiBenchmarkBase {
final Function1double f;
Floatx01({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction1Float,
Function1double>('Function1Float', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction1Float,
Function1double>('Function1Float', isLeaf: false),
super('FfiCall.Floatx01', isLeaf: isLeaf);
@override
void run() {
double x = 0.0;
for (int i = 0; i < N; i++) {
x += f(17.0);
}
expectApprox(x, N * (17.0 + 42.0));
}
}
class Floatx02 extends FfiBenchmarkBase {
final Function2double f;
Floatx02({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction2Float,
Function2double>('Function2Float', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction2Float,
Function2double>('Function2Float', isLeaf: false),
super('FfiCall.Floatx02', isLeaf: isLeaf);
@override
void run() {
double x = 0;
for (int i = 0; i < N; i++) {
x += f(1.0, 2.0);
}
expectApprox(x, N * (1.0 + 2.0));
}
}
class Floatx04 extends FfiBenchmarkBase {
final Function4double f;
Floatx04({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction4Float,
Function4double>('Function4Float', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction4Float,
Function4double>('Function4Float', isLeaf: false),
super('FfiCall.Floatx04', isLeaf: isLeaf);
@override
void run() {
double x = 0;
for (int i = 0; i < N; i++) {
x += f(1.0, 2.0, 3.0, 4.0);
}
final double expected = N * (1.0 + 2.0 + 3.0 + 4.0);
expectApprox(x, expected);
}
}
class Floatx10 extends FfiBenchmarkBase {
final Function10double f;
Floatx10({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction10Float,
Function10double>('Function10Float', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction10Float,
Function10double>('Function10Float', isLeaf: false),
super('FfiCall.Floatx10', isLeaf: isLeaf);
@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);
}
final double expected =
N * (1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.0 + 8.0 + 9.0 + 10.0);
expectApprox(x, expected);
}
}
class Floatx20 extends FfiBenchmarkBase {
final Function20double f;
Floatx20({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction20Float,
Function20double>('Function20Float', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction20Float,
Function20double>('Function20Float', isLeaf: false),
super('FfiCall.Floatx20', isLeaf: isLeaf);
@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 Doublex01 extends FfiBenchmarkBase {
final Function1double f;
Doublex01({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction1Double,
Function1double>('Function1Double', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction1Double,
Function1double>('Function1Double', isLeaf: false),
super('FfiCall.Doublex01', isLeaf: isLeaf);
@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 Doublex02 extends FfiBenchmarkBase {
final Function2double f;
Doublex02({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction2Double,
Function2double>('Function2Double', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction2Double,
Function2double>('Function2Double', isLeaf: false),
super('FfiCall.Doublex02', isLeaf: isLeaf);
@override
void run() {
double x = 0;
for (int i = 0; i < N; i++) {
x += f(1.0, 2.0);
}
final double expected = N * (1.0 + 2.0);
expectApprox(x, expected);
}
}
class Doublex04 extends FfiBenchmarkBase {
final Function4double f;
Doublex04({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction4Double,
Function4double>('Function4Double', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction4Double,
Function4double>('Function4Double', isLeaf: false),
super('FfiCall.Doublex04', isLeaf: isLeaf);
@override
void run() {
double x = 0;
for (int i = 0; i < N; i++) {
x += f(1.0, 2.0, 3.0, 4.0);
}
final double expected = N * (1.0 + 2.0 + 3.0 + 4.0);
expectApprox(x, expected);
}
}
class Doublex10 extends FfiBenchmarkBase {
final Function10double f;
Doublex10({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction10Double,
Function10double>('Function10Double', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction10Double,
Function10double>('Function10Double', isLeaf: false),
super('FfiCall.Doublex10', isLeaf: isLeaf);
@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);
}
final double expected =
N * (1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.0 + 8.0 + 9.0 + 10.0);
expectApprox(x, expected);
}
}
class Doublex20 extends FfiBenchmarkBase {
final Function20double f;
Doublex20({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<NativeFunction20Double,
Function20double>('Function20Double', isLeaf: true)
: ffiTestFunctions.lookupFunction<NativeFunction20Double,
Function20double>('Function20Double', isLeaf: false),
super('FfiCall.Doublex20', isLeaf: isLeaf);
@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 PointerUint8x01 extends FfiBenchmarkBase {
final Function1PointerUint8 f;
PointerUint8x01({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<Function1PointerUint8,
Function1PointerUint8>('Function1PointerUint8', isLeaf: true)
: ffiTestFunctions.lookupFunction<Function1PointerUint8,
Function1PointerUint8>('Function1PointerUint8', isLeaf: false),
super('FfiCall.PointerUint8x01', isLeaf: isLeaf);
Pointer<Uint8> p1 = nullptr;
@override
void setup() => p1 = calloc(N + 1);
@override
void teardown() => calloc.free(p1);
@override
void run() {
Pointer<Uint8> x = p1;
for (int i = 0; i < N; i++) {
x = f(x);
}
expectApprox(x.address, p1.address + N);
}
}
class PointerUint8x02 extends FfiBenchmarkBase {
final Function2PointerUint8 f;
PointerUint8x02({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<Function2PointerUint8,
Function2PointerUint8>('Function2PointerUint8', isLeaf: true)
: ffiTestFunctions.lookupFunction<Function2PointerUint8,
Function2PointerUint8>('Function2PointerUint8', isLeaf: false),
super('FfiCall.PointerUint8x02', isLeaf: isLeaf);
Pointer<Uint8> p1 = nullptr;
Pointer<Uint8> p2 = nullptr;
@override
void setup() {
p1 = calloc(N + 1);
p2 = p1.elementAt(1);
}
@override
void teardown() {
calloc.free(p1);
}
@override
void run() {
Pointer<Uint8> x = p1;
for (int i = 0; i < N; i++) {
x = f(x, p2);
}
expectEquals(x.address, p1.address + N * sizeOf<Uint8>());
}
}
class PointerUint8x04 extends FfiBenchmarkBase {
final Function4PointerUint8 f;
PointerUint8x04({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<Function4PointerUint8,
Function4PointerUint8>('Function4PointerUint8', isLeaf: true)
: ffiTestFunctions.lookupFunction<Function4PointerUint8,
Function4PointerUint8>('Function4PointerUint8', isLeaf: false),
super('FfiCall.PointerUint8x04', isLeaf: isLeaf);
Pointer<Uint8> p1 = nullptr;
Pointer<Uint8> p2 = nullptr;
Pointer<Uint8> p3 = nullptr;
Pointer<Uint8> p4 = nullptr;
@override
void setup() {
p1 = calloc(N + 1);
p2 = p1.elementAt(1);
p3 = p1.elementAt(2);
p4 = p1.elementAt(3);
}
@override
void teardown() {
calloc.free(p1);
}
@override
void run() {
Pointer<Uint8> x = p1;
for (int i = 0; i < N; i++) {
x = f(x, p2, p3, p4);
}
expectEquals(x.address, p1.address + N * sizeOf<Uint8>());
}
}
class PointerUint8x10 extends FfiBenchmarkBase {
final Function10PointerUint8 f;
PointerUint8x10({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<Function10PointerUint8,
Function10PointerUint8>('Function10PointerUint8', isLeaf: true)
: ffiTestFunctions
.lookupFunction<Function10PointerUint8, Function10PointerUint8>(
'Function10PointerUint8',
isLeaf: false),
super('FfiCall.PointerUint8x10', isLeaf: isLeaf);
Pointer<Uint8> p1 = nullptr;
Pointer<Uint8> p2 = nullptr;
Pointer<Uint8> p3 = nullptr;
Pointer<Uint8> p4 = nullptr;
Pointer<Uint8> p5 = nullptr;
Pointer<Uint8> p6 = nullptr;
Pointer<Uint8> p7 = nullptr;
Pointer<Uint8> p8 = nullptr;
Pointer<Uint8> p9 = nullptr;
Pointer<Uint8> p10 = nullptr;
@override
void setup() {
p1 = calloc(N + 1);
p2 = p1.elementAt(1);
p3 = p1.elementAt(2);
p4 = p1.elementAt(3);
p5 = p1.elementAt(4);
p6 = p1.elementAt(5);
p7 = p1.elementAt(6);
p8 = p1.elementAt(7);
p9 = p1.elementAt(8);
p10 = p1.elementAt(9);
}
@override
void teardown() {
calloc.free(p1);
}
@override
void run() {
Pointer<Uint8> x = p1;
for (int i = 0; i < N; i++) {
x = f(x, p2, p3, p4, p5, p6, p7, p8, p9, p10);
}
expectEquals(x.address, p1.address + N * sizeOf<Uint8>());
}
}
class PointerUint8x20 extends FfiBenchmarkBase {
final Function20PointerUint8 f;
PointerUint8x20({isLeaf: false})
: f = isLeaf
? ffiTestFunctions.lookupFunction<Function20PointerUint8,
Function20PointerUint8>('Function20PointerUint8', isLeaf: true)
: ffiTestFunctions
.lookupFunction<Function20PointerUint8, Function20PointerUint8>(
'Function20PointerUint8',
isLeaf: false),
super('FfiCall.PointerUint8x20', isLeaf: isLeaf);
Pointer<Uint8> p1 = nullptr;
Pointer<Uint8> p2 = nullptr;
Pointer<Uint8> p3 = nullptr;
Pointer<Uint8> p4 = nullptr;
Pointer<Uint8> p5 = nullptr;
Pointer<Uint8> p6 = nullptr;
Pointer<Uint8> p7 = nullptr;
Pointer<Uint8> p8 = nullptr;
Pointer<Uint8> p9 = nullptr;
Pointer<Uint8> p10 = nullptr;
Pointer<Uint8> p11 = nullptr;
Pointer<Uint8> p12 = nullptr;
Pointer<Uint8> p13 = nullptr;
Pointer<Uint8> p14 = nullptr;
Pointer<Uint8> p15 = nullptr;
Pointer<Uint8> p16 = nullptr;
Pointer<Uint8> p17 = nullptr;
Pointer<Uint8> p18 = nullptr;
Pointer<Uint8> p19 = nullptr;
Pointer<Uint8> p20 = nullptr;
@override
void setup() {
p1 = calloc(N + 1);
p2 = p1.elementAt(1);
p3 = p1.elementAt(2);
p4 = p1.elementAt(3);
p5 = p1.elementAt(4);
p6 = p1.elementAt(5);
p7 = p1.elementAt(6);
p8 = p1.elementAt(7);
p9 = p1.elementAt(8);
p10 = p1.elementAt(9);
p11 = p1.elementAt(10);
p12 = p1.elementAt(11);
p13 = p1.elementAt(12);
p14 = p1.elementAt(13);
p15 = p1.elementAt(14);
p16 = p1.elementAt(15);
p17 = p1.elementAt(16);
p18 = p1.elementAt(17);
p19 = p1.elementAt(18);
p20 = p1.elementAt(19);
}
@override
void teardown() {
calloc.free(p1);
}
@override
void run() {
Pointer<Uint8> 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);
}
expectEquals(x.address, p1.address + N * sizeOf<Uint8>());
}
}
class MyClass {
int a;
MyClass(this.a);
}
class Handlex01 extends FfiBenchmarkBase {
final Function1Object f;
Handlex01()
: f = ffiTestFunctions.lookupFunction<NativeFunction1Handle,
Function1Object>('Function1Handle', isLeaf: false),
super('FfiCall.Handlex01', isLeaf: false);
@override
void run() {
final p1 = MyClass(123);
Object x = p1;
for (int i = 0; i < N; i++) {
x = f(x);
}
expectIdentical(x, p1);
}
}
class Handlex02 extends FfiBenchmarkBase {
final Function2Object f;
Handlex02()
: f = ffiTestFunctions.lookupFunction<NativeFunction2Handle,
Function2Object>('Function2Handle', isLeaf: false),
super('FfiCall.Handlex02', isLeaf: false);
@override
void run() {
final p1 = MyClass(123);
final p2 = MyClass(2);
Object x = p1;
for (int i = 0; i < N; i++) {
x = f(x, p2);
}
expectIdentical(x, p1);
}
}
class Handlex04 extends FfiBenchmarkBase {
final Function4Object f;
Handlex04()
: f = ffiTestFunctions.lookupFunction<NativeFunction4Handle,
Function4Object>('Function4Handle', isLeaf: false),
super('FfiCall.Handlex04', isLeaf: false);
@override
void run() {
final p1 = MyClass(123);
final p2 = MyClass(2);
final p3 = MyClass(3);
final p4 = MyClass(4);
Object x = p1;
for (int i = 0; i < N; i++) {
x = f(x, p2, p3, p4);
}
expectIdentical(x, p1);
}
}
class Handlex10 extends FfiBenchmarkBase {
final Function10Object f;
Handlex10()
: f = ffiTestFunctions.lookupFunction<NativeFunction10Handle,
Function10Object>('Function10Handle', isLeaf: false),
super('FfiCall.Handlex10', isLeaf: false);
@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);
Object x = p1;
for (int i = 0; i < N; i++) {
x = f(x, p2, p3, p4, p5, p6, p7, p8, p9, p10);
}
expectIdentical(x, p1);
}
}
class Handlex20 extends FfiBenchmarkBase {
final Function20Object f;
Handlex20()
: f = ffiTestFunctions.lookupFunction<NativeFunction20Handle,
Function20Object>('Function20Handle', isLeaf: false),
super('FfiCall.Handlex20', isLeaf: false);
@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() {
final benchmarks = [
() => Uint8x01(),
() => Uint8x01(isLeaf: true),
() => Uint16x01(),
() => Uint32x01(),
() => Uint64x01(),
() => Int8x01(),
() => Int8x01(isLeaf: true),
() => Int16x01(),
() => Int32x01(),
() => Int32x02(),
() => Int32x04(),
() => Int32x10(),
() => Int32x20(),
() => Int64x01(),
() => Int64x02(),
() => Int64x04(),
() => Int64x10(),
() => Int64x20(),
() => Int64x20(isLeaf: true),
() => Int64Mintx01(),
() => Int64Mintx01(isLeaf: true),
() => Floatx01(),
() => Floatx02(),
() => Floatx04(),
() => Floatx10(),
() => Floatx20(),
() => Floatx20(isLeaf: true),
() => Doublex01(),
() => Doublex02(),
() => Doublex04(),
() => Doublex10(),
() => Doublex20(),
() => Doublex20(isLeaf: true),
() => PointerUint8x01(),
() => PointerUint8x02(),
() => PointerUint8x04(),
() => PointerUint8x10(),
() => PointerUint8x20(),
() => PointerUint8x20(isLeaf: true),
() => Handlex01(),
() => Handlex02(),
() => Handlex04(),
() => Handlex10(),
() => Handlex20(),
];
for (final benchmark in benchmarks) {
benchmark().report();
}
}