From 4af84694934bf9275b83f18d5dda6eedede179de Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Tue, 9 May 2023 09:50:24 +0000 Subject: [PATCH] [benchmarks/ffi] Cleanup benchmarks * Added a name-filter to every benchmark. * Addressed lints. * We don't run the legacy copies anymore, so deleted dart2 dirs. Change-Id: I65705749c5c90aad77d1fb93ea4a0d4e8b656cd4 Cq-Include-Trybots: luci.dart.try:benchmark-linux-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/301522 Reviewed-by: Jonas Termansen Commit-Queue: Daco Harkes --- .../FfiAsTypedList/dart/FfiAsTypedList.dart | 13 +- .../FfiAsTypedList/dart2/FfiAsTypedList.dart | 51 -- .../FfiBoringssl/dart/FfiBoringssl.dart | 15 +- .../FfiBoringssl/dart2/FfiBoringssl.dart | 151 ----- benchmarks/FfiBoringssl/dart2/digest.dart | 101 --- .../FfiBoringssl/dart2/dlopen_helper.dart | 63 -- benchmarks/FfiBoringssl/dart2/types.dart | 33 - benchmarks/FfiCall/dart/FfiCall.dart | 11 +- benchmarks/FfiMemory/dart/FfiMemory.dart | 45 +- benchmarks/FfiMemory/dart2/FfiMemory.dart | 599 ------------------ benchmarks/FfiStruct/dart/FfiStruct.dart | 15 +- .../FfiStructCopy/dart/FfiStructCopy.dart | 21 +- 12 files changed, 68 insertions(+), 1050 deletions(-) delete mode 100644 benchmarks/FfiAsTypedList/dart2/FfiAsTypedList.dart delete mode 100644 benchmarks/FfiBoringssl/dart2/FfiBoringssl.dart delete mode 100644 benchmarks/FfiBoringssl/dart2/digest.dart delete mode 100644 benchmarks/FfiBoringssl/dart2/dlopen_helper.dart delete mode 100644 benchmarks/FfiBoringssl/dart2/types.dart delete mode 100644 benchmarks/FfiMemory/dart2/FfiMemory.dart diff --git a/benchmarks/FfiAsTypedList/dart/FfiAsTypedList.dart b/benchmarks/FfiAsTypedList/dart/FfiAsTypedList.dart index f32f5d06e39..39d0e037568 100644 --- a/benchmarks/FfiAsTypedList/dart/FfiAsTypedList.dart +++ b/benchmarks/FfiAsTypedList/dart/FfiAsTypedList.dart @@ -39,11 +39,16 @@ class FromPointerInt8 extends BenchmarkBase { // Main driver. // -void main() { +void main(List args) { final benchmarks = [ - () => FromPointerInt8(), + FromPointerInt8.new, ]; - for (final benchmark in benchmarks) { - benchmark().report(); + + final filter = args.firstOrNull; + for (var constructor in benchmarks) { + final benchmark = constructor(); + if (filter == null || benchmark.name.contains(filter)) { + benchmark.report(); + } } } diff --git a/benchmarks/FfiAsTypedList/dart2/FfiAsTypedList.dart b/benchmarks/FfiAsTypedList/dart2/FfiAsTypedList.dart deleted file mode 100644 index bab621d5b76..00000000000 --- a/benchmarks/FfiAsTypedList/dart2/FfiAsTypedList.dart +++ /dev/null @@ -1,51 +0,0 @@ -// 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. - -// Micro-benchmark for creating TypeData lists from Pointers. -// -// The FfiMemory benchmark tests accessing memory through TypedData. - -// @dart=2.9 - -import 'dart:ffi'; - -import 'package:benchmark_harness/benchmark_harness.dart'; -import 'package:ffi/ffi.dart'; - -// -// Benchmark fixture. -// - -// Number of repeats: 1000 -const N = 1000; - -class FromPointerInt8 extends BenchmarkBase { - Pointer pointer = nullptr; - FromPointerInt8() : super('FfiAsTypedList.FromPointerInt8'); - - @override - void setup() => pointer = calloc(1); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - for (var i = 0; i < N; i++) { - pointer.asTypedList(1); - } - } -} - -// -// Main driver. -// - -void main() { - final benchmarks = [ - () => FromPointerInt8(), - ]; - for (final benchmark in benchmarks) { - benchmark().report(); - } -} diff --git a/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart b/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart index 8781c43542d..018f33bc611 100644 --- a/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart +++ b/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart @@ -138,12 +138,17 @@ class DigestDartMemory extends BenchmarkBase { // Main driver. // -void main() { +void main(List args) { final benchmarks = [ - () => DigestCMemory(), - () => DigestDartMemory(), + DigestCMemory.new, + DigestDartMemory.new, ]; - for (final benchmark in benchmarks) { - benchmark().report(); + + final filter = args.firstOrNull; + for (var constructor in benchmarks) { + final benchmark = constructor(); + if (filter == null || benchmark.name.contains(filter)) { + benchmark.report(); + } } } diff --git a/benchmarks/FfiBoringssl/dart2/FfiBoringssl.dart b/benchmarks/FfiBoringssl/dart2/FfiBoringssl.dart deleted file mode 100644 index 635fa574ba6..00000000000 --- a/benchmarks/FfiBoringssl/dart2/FfiBoringssl.dart +++ /dev/null @@ -1,151 +0,0 @@ -// 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. - -// Macro-benchmark for ffi with boringssl. - -// @dart=2.9 - -import 'dart:convert'; -import 'dart:ffi'; -import 'dart:typed_data'; - -import 'package:benchmark_harness/benchmark_harness.dart'; -import 'package:ffi/ffi.dart'; - -import 'digest.dart'; -import 'types.dart'; - -// -// BoringSSL functions -// - -Uint8List inventData(int length) { - final result = Uint8List(length); - for (int i = 0; i < length; i++) { - result[i] = i % 256; - } - return result; -} - -Uint8List toUint8List(Pointer bytes, int length) { - final result = Uint8List(length); - final uint8bytes = bytes.asUint8Pointer(); - for (int i = 0; i < length; i++) { - result[i] = uint8bytes[i]; - } - return result; -} - -void copyFromUint8ListToTarget(Uint8List source, Pointer target) { - final int length = source.length; - final uint8target = target.asUint8Pointer(); - for (int i = 0; i < length; i++) { - uint8target[i] = source[i]; - } -} - -String hash(Pointer data, int length, Pointer hashAlgorithm) { - final context = EVP_MD_CTX_new(); - EVP_DigestInit(context, hashAlgorithm); - EVP_DigestUpdate(context, data, length); - final int resultSize = EVP_MD_CTX_size(context); - final Pointer result = calloc(resultSize).cast(); - EVP_DigestFinal(context, result, nullptr); - EVP_MD_CTX_free(context); - final String hash = base64Encode(toUint8List(result, resultSize)); - calloc.free(result); - return hash; -} - -// -// Benchmark fixtures. -// - -// Number of repeats: 1 && Length in bytes: 10000000 -// * CPU: Intel(R) Xeon(R) Gold 6154 -// * Architecture: x64 -// * 23000 - 52000000 us (without optimizations) -// * 23000 - 30000 us (with optimizations) -const int L = 1000; // Length of data in bytes. - -final hashAlgorithm = EVP_sha512(); - -// Hash of generated data of `L` bytes with `hashAlgorithm`. -const String expectedHash = - 'bNLtqb+cBZcSkCmwBUuB5DP2uLe0madetwXv10usGUFJg1sdGhTEi+aW5NWIRW1RKiLq56obV74rVurn014Iyw=='; - -/// This benchmark runs a digest algorithm on data residing in C memory. -/// -/// This benchmark is intended as macro benchmark with a realistic workload. -class DigestCMemory extends BenchmarkBase { - DigestCMemory() : super('FfiBoringssl.DigestCMemory'); - - Pointer data; // Data in C memory that we want to digest. - - @override - void setup() { - data = calloc(L).cast(); - copyFromUint8ListToTarget(inventData(L), data); - hash(data, L, hashAlgorithm); - } - - @override - void teardown() { - calloc.free(data); - } - - @override - void run() { - final String result = hash(data, L, hashAlgorithm); - if (result != expectedHash) { - throw Exception('$name: Unexpected result: $result'); - } - } -} - -/// This benchmark runs a digest algorithm on data residing in Dart memory. -/// -/// This benchmark is intended as macro benchmark with a realistic workload. -class DigestDartMemory extends BenchmarkBase { - DigestDartMemory() : super('FfiBoringssl.DigestDartMemory'); - - Uint8List data; // Data in C memory that we want to digest. - - @override - void setup() { - data = inventData(L); - final Pointer dataInC = calloc(L).cast(); - copyFromUint8ListToTarget(data, dataInC); - hash(dataInC, L, hashAlgorithm); - calloc.free(dataInC); - } - - @override - void teardown() {} - - @override - void run() { - final Pointer dataInC = calloc(L).cast(); - copyFromUint8ListToTarget(data, dataInC); - final String result = hash(dataInC, L, hashAlgorithm); - calloc.free(dataInC); - if (result != expectedHash) { - throw Exception('$name: Unexpected result: $result'); - } - } -} - -// -// Main driver. -// - -void main() { - final benchmarks = [ - () => DigestCMemory(), - () => DigestDartMemory(), - ]; - for (final benchmark in benchmarks) { - benchmark().report(); - } -} diff --git a/benchmarks/FfiBoringssl/dart2/digest.dart b/benchmarks/FfiBoringssl/dart2/digest.dart deleted file mode 100644 index 290df60b478..00000000000 --- a/benchmarks/FfiBoringssl/dart2/digest.dart +++ /dev/null @@ -1,101 +0,0 @@ -// 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. - -// @dart=2.9 - -import 'dart:ffi'; -import 'dart:io'; - -import 'dlopen_helper.dart'; -import 'types.dart'; - -// See: -// https://commondatastorage.googleapis.com/chromium-boringssl-docs/digest.h.html - -DynamicLibrary openSsl() { - // Force load crypto. - dlopenPlatformSpecific('crypto', - path: Platform.script.resolve('../native/out/').path); - final ssl = dlopenPlatformSpecific('ssl', - path: Platform.script.resolve('../native/out/').path); - return ssl; -} - -final DynamicLibrary ssl = openSsl(); - -/// The following functions return EVP_MD objects that implement the named -/// hash function. -/// -/// ```c -/// const EVP_MD *EVP_sha512(void); -/// ``` -final Pointer Function() EVP_sha512 = - ssl.lookupFunction Function(), Pointer Function()>( - 'EVP_sha512'); - -/// EVP_MD_CTX_new allocates and initialises a fresh EVP_MD_CTX and returns it, -/// or NULL on allocation failure. The caller must use EVP_MD_CTX_free to -/// release the resulting object. -/// -/// ```c -/// EVP_MD_CTX *EVP_MD_CTX_new(void); -/// ``` -final Pointer Function() EVP_MD_CTX_new = ssl.lookupFunction< - Pointer Function(), - Pointer Function()>('EVP_MD_CTX_new'); - -/// EVP_MD_CTX_free calls EVP_MD_CTX_cleanup and then frees ctx itself. -/// -/// ```c -/// void EVP_MD_CTX_free(EVP_MD_CTX *ctx); -/// ``` -final void Function(Pointer) EVP_MD_CTX_free = ssl.lookupFunction< - Void Function(Pointer), - void Function(Pointer)>('EVP_MD_CTX_free'); - -/// EVP_DigestInit acts like EVP_DigestInit_ex except that ctx is initialised -/// before use. -/// -/// ```c -/// int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); -/// ``` -final int Function(Pointer, Pointer) EVP_DigestInit = - ssl.lookupFunction, Pointer), - int Function(Pointer, Pointer)>('EVP_DigestInit'); - -/// EVP_DigestUpdate hashes len bytes from data into the hashing operation -/// in ctx. It returns one. -/// -/// ```c -/// int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, -/// size_t len); -/// ``` -final int Function(Pointer, Pointer, int) EVP_DigestUpdate = - ssl.lookupFunction< - Int32 Function(Pointer, Pointer, IntPtr), - int Function( - Pointer, Pointer, int)>('EVP_DigestUpdate'); - -/// EVP_DigestFinal acts like EVP_DigestFinal_ex except that EVP_MD_CTX_cleanup -/// is called on ctx before returning. -/// -/// ```c -/// int EVP_DigestFinal(EVP_MD_CTX *ctx, uint8_t *md_out, -/// unsigned int *out_size); -/// ``` -final int Function(Pointer, Pointer, Pointer) - EVP_DigestFinal = ssl.lookupFunction< - Int32 Function(Pointer, Pointer, Pointer), - int Function(Pointer, Pointer, - Pointer)>('EVP_DigestFinal'); - -/// EVP_MD_CTX_size returns the digest size of ctx, in bytes. It will crash if -/// a digest hasn't been set on ctx. -/// -/// ```c -/// size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx); -/// ``` -final int Function(Pointer) EVP_MD_CTX_size = ssl.lookupFunction< - IntPtr Function(Pointer), - int Function(Pointer)>('EVP_MD_CTX_size'); diff --git a/benchmarks/FfiBoringssl/dart2/dlopen_helper.dart b/benchmarks/FfiBoringssl/dart2/dlopen_helper.dart deleted file mode 100644 index 128bff7dd23..00000000000 --- a/benchmarks/FfiBoringssl/dart2/dlopen_helper.dart +++ /dev/null @@ -1,63 +0,0 @@ -// 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. - -// @dart=2.9 - -import 'dart:ffi'; -import 'dart:io'; - -const arm = 'arm'; -const arm64 = 'arm64'; -const ia32 = 'ia32'; -const x64 = 'x64'; - -// https://stackoverflow.com/questions/45125516/possible-values-for-uname-m -final _unames = { - 'arm': arm, - 'aarch64_be': arm64, - 'aarch64': arm64, - 'armv8b': arm64, - 'armv8l': arm64, - 'i386': ia32, - 'i686': ia32, - 'x86_64': x64, -}; - -String _checkRunningMode(String architecture) { - // Check if we're running in 32bit mode. - final int pointerSize = sizeOf(); - if (pointerSize == 4 && architecture == x64) return ia32; - if (pointerSize == 4 && architecture == arm64) return arm; - - return architecture; -} - -String _architecture() { - final String uname = Process.runSync('uname', ['-m']).stdout.trim(); - final String architecture = _unames[uname]; - if (architecture == null) { - throw Exception('Unrecognized architecture: "$uname"'); - } - - // Check if we're running in 32bit mode. - return _checkRunningMode(architecture); -} - -String _platformPath(String name, {String path = ''}) { - if (Platform.isMacOS || Platform.isIOS) { - return '${path}mac/${_architecture()}/lib$name.dylib'; - } - - if (Platform.isWindows) { - return '${path}win/${_checkRunningMode(x64)}/$name.dll'; - } - - // Unknown platforms default to Unix implementation. - return '${path}linux/${_architecture()}/lib$name.so'; -} - -DynamicLibrary dlopenPlatformSpecific(String name, {String path}) { - final String fullPath = _platformPath(name, path: path); - return DynamicLibrary.open(fullPath); -} diff --git a/benchmarks/FfiBoringssl/dart2/types.dart b/benchmarks/FfiBoringssl/dart2/types.dart deleted file mode 100644 index 5ceb6a95c00..00000000000 --- a/benchmarks/FfiBoringssl/dart2/types.dart +++ /dev/null @@ -1,33 +0,0 @@ -// 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. - -// ignore_for_file: camel_case_types - -// @dart=2.9 - -import 'dart:ffi'; - -/// digest algorithm. -class EVP_MD extends Opaque {} - -/// digest context. -class EVP_MD_CTX extends Opaque {} - -/// Type for `void*` used to represent opaque data. -class Data extends Opaque { - static Pointer fromUint8Pointer(Pointer p) => p.cast(); -} - -extension DataPointerAsUint8Pointer on Pointer { - Pointer asUint8Pointer() => cast(); -} - -/// Type for `uint8_t*` used to represent byte data. -class Bytes extends Opaque { - static Pointer fromUint8Pointer(Pointer p) => p.cast(); -} - -extension BytesPointerAsUint8Pointer on Pointer { - Pointer asUint8Pointer() => cast(); -} diff --git a/benchmarks/FfiCall/dart/FfiCall.dart b/benchmarks/FfiCall/dart/FfiCall.dart index b0523cd6010..fd1a15da503 100644 --- a/benchmarks/FfiCall/dart/FfiCall.dart +++ b/benchmarks/FfiCall/dart/FfiCall.dart @@ -82,7 +82,7 @@ class Int64Mintx01 extends FfiBenchmarkBase { // Main driver. // -void main() { +void main(List args) { // Force loading the dylib with RLTD_GLOBAL so that the // Native benchmarks below can do process lookup. dlopenGlobalPlatformSpecific('native_functions', @@ -147,7 +147,12 @@ void main() { Handlex20.new, Handlex20Native.new, ]; - for (var benchmark in benchmarks) { - benchmark().report(); + + final filter = args.firstOrNull; + for (var constructor in benchmarks) { + final benchmark = constructor(); + if (filter == null || benchmark.name.contains(filter)) { + benchmark.report(); + } } } diff --git a/benchmarks/FfiMemory/dart/FfiMemory.dart b/benchmarks/FfiMemory/dart/FfiMemory.dart index 5ca2954cd03..83ac8ba1f90 100644 --- a/benchmarks/FfiMemory/dart/FfiMemory.dart +++ b/benchmarks/FfiMemory/dart/FfiMemory.dart @@ -12,8 +12,8 @@ import 'dart:ffi'; import 'dart:typed_data'; -import 'package:ffi/ffi.dart'; import 'package:benchmark_harness/benchmark_harness.dart'; +import 'package:ffi/ffi.dart'; // // Pointer store. @@ -574,26 +574,31 @@ class PointerInt64Mint extends BenchmarkBase { // Main driver. // -void main() { +void main(List args) { final benchmarks = [ - () => PointerInt8(), - () => PointerInt8TypedDataNew(), - () => PointerInt8TypedDataReuse(), - () => PointerUint8(), - () => PointerInt16(), - () => PointerUint16(), - () => PointerInt32(), - () => PointerUint32(), - () => PointerUint32Unaligned(), - () => PointerInt64(), - () => PointerInt64Mint(), - () => PointerUint64(), - () => PointerUintPtr(), - () => PointerFloat(), - () => PointerDouble(), - () => PointerPointer(), + PointerInt8.new, + PointerInt8TypedDataNew.new, + PointerInt8TypedDataReuse.new, + PointerUint8.new, + PointerInt16.new, + PointerUint16.new, + PointerInt32.new, + PointerUint32.new, + PointerUint32Unaligned.new, + PointerInt64.new, + PointerInt64Mint.new, + PointerUint64.new, + PointerUintPtr.new, + PointerFloat.new, + PointerDouble.new, + PointerPointer.new, ]; - for (final benchmark in benchmarks) { - benchmark().report(); + + final filter = args.firstOrNull; + for (var constructor in benchmarks) { + final benchmark = constructor(); + if (filter == null || benchmark.name.contains(filter)) { + benchmark.report(); + } } } diff --git a/benchmarks/FfiMemory/dart2/FfiMemory.dart b/benchmarks/FfiMemory/dart2/FfiMemory.dart deleted file mode 100644 index d57712c52e5..00000000000 --- a/benchmarks/FfiMemory/dart2/FfiMemory.dart +++ /dev/null @@ -1,599 +0,0 @@ -// 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. - -// Micro-benchmarks for ffi memory stores and loads. -// -// These micro benchmarks track the speed of reading and writing C memory from -// Dart with a specific marshalling and unmarshalling of data. - -// @dart=2.9 - -import 'dart:ffi'; -import 'dart:typed_data'; - -import 'package:ffi/ffi.dart'; -import 'package:benchmark_harness/benchmark_harness.dart'; - -// -// Pointer store. -// - -void doStoreInt8(Pointer pointer, int length) { - for (int i = 0; i < length; i++) { - pointer[i] = 1; - } -} - -void doStoreInt8TypedData(Int8List typedData, int length) { - for (int i = 0; i < length; i++) { - typedData[i] = 1; - } -} - -void doStoreUint8(Pointer pointer, int length) { - for (int i = 0; i < length; i++) { - pointer[i] = 1; - } -} - -void doStoreInt16(Pointer pointer, int length) { - for (int i = 0; i < length; i++) { - pointer[i] = 1; - } -} - -void doStoreUint16(Pointer pointer, int length) { - for (int i = 0; i < length; i++) { - pointer[i] = 1; - } -} - -void doStoreInt32(Pointer pointer, int length) { - for (int i = 0; i < length; i++) { - pointer[i] = 1; - } -} - -void doStoreUint32(Pointer pointer, int length) { - for (int i = 0; i < length; i++) { - pointer[i] = 1; - } -} - -void doStoreInt64(Pointer pointer, int length) { - for (int i = 0; i < length; i++) { - pointer[i] = 1; - } -} - -void doStoreUint64(Pointer pointer, int length) { - for (int i = 0; i < length; i++) { - pointer[i] = 1; - } -} - -void doStoreUintPtr(Pointer pointer, int length) { - for (int i = 0; i < length; i++) { - pointer[i] = 1; - } -} - -void doStoreFloat(Pointer pointer, int length) { - for (int i = 0; i < length; i++) { - pointer[i] = 1.0; - } -} - -void doStoreDouble(Pointer pointer, int length) { - for (int i = 0; i < length; i++) { - pointer[i] = 1.0; - } -} - -void doStorePointer( - Pointer> pointer, int length, Pointer data) { - for (int i = 0; i < length; i++) { - pointer[i] = data; - } -} - -void doStoreInt64Mint(Pointer pointer, int length) { - for (int i = 0; i < length; i++) { - pointer[i] = 0x7FFFFFFFFFFFFFFF; - } -} - -// -// Pointer load. -// - -int doLoadInt8(Pointer pointer, int length) { - int x = 0; - for (int i = 0; i < length; i++) { - x += pointer[i]; - } - return x; -} - -int doLoadInt8TypedData(Int8List typedData, int length) { - int x = 0; - for (int i = 0; i < length; i++) { - x += typedData[i]; - } - return x; -} - -int doLoadUint8(Pointer pointer, int length) { - int x = 0; - for (int i = 0; i < length; i++) { - x += pointer[i]; - } - return x; -} - -int doLoadInt16(Pointer pointer, int length) { - int x = 0; - for (int i = 0; i < length; i++) { - x += pointer[i]; - } - return x; -} - -int doLoadUint16(Pointer pointer, int length) { - int x = 0; - for (int i = 0; i < length; i++) { - x += pointer[i]; - } - return x; -} - -int doLoadInt32(Pointer pointer, int length) { - int x = 0; - for (int i = 0; i < length; i++) { - x += pointer[i]; - } - return x; -} - -int doLoadUint32(Pointer pointer, int length) { - int x = 0; - for (int i = 0; i < length; i++) { - x += pointer[i]; - } - return x; -} - -int doLoadInt64(Pointer pointer, int length) { - int x = 0; - for (int i = 0; i < length; i++) { - x += pointer[i]; - } - return x; -} - -int doLoadUint64(Pointer pointer, int length) { - int x = 0; - for (int i = 0; i < length; i++) { - x += pointer[i]; - } - return x; -} - -int doLoadUintPtr(Pointer pointer, int length) { - int x = 0; - for (int i = 0; i < length; i++) { - x += pointer[i]; - } - return x; -} - -double doLoadFloat(Pointer pointer, int length) { - double x = 0; - for (int i = 0; i < length; i++) { - x += pointer[i]; - } - return x; -} - -double doLoadDouble(Pointer pointer, int length) { - double x = 0; - for (int i = 0; i < length; i++) { - x += pointer[i]; - } - return x; -} - -// Aggregates pointers through aggregating their addresses. -int doLoadPointer(Pointer> pointer, int length) { - Pointer x; - int address_xor = 0; - for (int i = 0; i < length; i++) { - x = pointer[i]; - address_xor ^= x.address; - } - return address_xor; -} - -int doLoadInt64Mint(Pointer pointer, int length) { - int x = 0; - for (int i = 0; i < length; i++) { - x += pointer[i]; - } - return x; -} - -// -// Benchmark fixtures. -// - -// Number of repeats: 1000 -// * CPU: Intel(R) Xeon(R) Gold 6154 -// * Architecture: x64 -// * 48000 - 125000 us (without optimizations) -// * 14 - ??? us (expected with optimizations, on par with typed data) -const N = 1000; - -class PointerInt8 extends BenchmarkBase { - Pointer pointer; - PointerInt8() : super('FfiMemory.PointerInt8'); - - @override - void setup() => pointer = calloc(N); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreInt8(pointer, N); - final int x = doLoadInt8(pointer, N); - if (x != N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerInt8TypedDataNew extends BenchmarkBase { - Pointer pointer; - PointerInt8TypedDataNew() : super('FfiMemory.PointerInt8TypedDataNew'); - - @override - void setup() { - pointer = calloc(N); - } - - @override - void teardown() { - calloc.free(pointer); - pointer = null; - } - - @override - void run() { - final typedData = pointer.asTypedList(N); - doStoreInt8TypedData(typedData, N); - final int x = doLoadInt8TypedData(typedData, N); - if (x != N) { - throw Exception('$name: Unexpected result: $x, expected $N'); - } - } -} - -class PointerInt8TypedDataReuse extends BenchmarkBase { - Pointer pointer; - Int8List typedData; - PointerInt8TypedDataReuse() : super('FfiMemory.PointerInt8TypedDataReuse'); - - @override - void setup() { - pointer = calloc(N); - typedData = pointer.asTypedList(N); - } - - @override - void teardown() { - calloc.free(pointer); - pointer = null; - typedData = null; - } - - @override - void run() { - doStoreInt8TypedData(typedData, N); - final int x = doLoadInt8TypedData(typedData, N); - if (x != N) { - throw Exception('$name: Unexpected result: $x, expected $N'); - } - } -} - -class PointerUint8 extends BenchmarkBase { - Pointer pointer; - PointerUint8() : super('FfiMemory.PointerUint8'); - - @override - void setup() => pointer = calloc(N); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreUint8(pointer, N); - final int x = doLoadUint8(pointer, N); - if (x != N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerInt16 extends BenchmarkBase { - Pointer pointer; - PointerInt16() : super('FfiMemory.PointerInt16'); - - @override - void setup() => pointer = calloc(N); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreInt16(pointer, N); - final int x = doLoadInt16(pointer, N); - if (x != N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerUint16 extends BenchmarkBase { - Pointer pointer; - PointerUint16() : super('FfiMemory.PointerUint16'); - - @override - void setup() => pointer = calloc(N); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreUint16(pointer, N); - final int x = doLoadUint16(pointer, N); - if (x != N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerInt32 extends BenchmarkBase { - Pointer pointer; - PointerInt32() : super('FfiMemory.PointerInt32'); - - @override - void setup() => pointer = calloc(N); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreInt32(pointer, N); - final int x = doLoadInt32(pointer, N); - if (x != N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerUint32 extends BenchmarkBase { - Pointer pointer; - PointerUint32() : super('FfiMemory.PointerUint32'); - - @override - void setup() => pointer = calloc(N); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreUint32(pointer, N); - final int x = doLoadUint32(pointer, N); - if (x != N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerUint32Unaligned extends BenchmarkBase { - Pointer pointer; - Pointer unalignedPointer; - PointerUint32Unaligned() : super('FfiMemory.PointerUint32Unaligned'); - - @override - void setup() { - pointer = calloc(N + 1); - unalignedPointer = Pointer.fromAddress(pointer.address + 1); - } - - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreUint32(unalignedPointer, N); - final int x = doLoadUint32(unalignedPointer, N); - if (x != N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerInt64 extends BenchmarkBase { - Pointer pointer; - PointerInt64() : super('FfiMemory.PointerInt64'); - - @override - void setup() => pointer = calloc(N); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreInt64(pointer, N); - final int x = doLoadInt64(pointer, N); - if (x != N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerUint64 extends BenchmarkBase { - Pointer pointer; - PointerUint64() : super('FfiMemory.PointerUint64'); - - @override - void setup() => pointer = calloc(N); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreUint64(pointer, N); - final int x = doLoadUint64(pointer, N); - if (x != N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerUintPtr extends BenchmarkBase { - Pointer pointer; - PointerUintPtr() : super('FfiMemory.PointerUintPtr'); - - @override - void setup() => pointer = calloc(N); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreUintPtr(pointer, N); - final int x = doLoadUintPtr(pointer, N); - if (x != N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerFloat extends BenchmarkBase { - Pointer pointer; - PointerFloat() : super('FfiMemory.PointerFloat'); - - @override - void setup() => pointer = calloc(N); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreFloat(pointer, N); - final double x = doLoadFloat(pointer, N); - if (0.99 * N > x || x > 1.01 * N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerDouble extends BenchmarkBase { - Pointer pointer; - PointerDouble() : super('FfiMemory.PointerDouble'); - - @override - void setup() => pointer = calloc(N); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreDouble(pointer, N); - final double x = doLoadDouble(pointer, N); - if (0.99 * N > x || x > 1.01 * N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerPointer extends BenchmarkBase { - Pointer> pointer; - Pointer data; - PointerPointer() : super('FfiMemory.PointerPointer'); - - @override - void setup() { - pointer = calloc(N); - data = calloc(); - } - - @override - void teardown() { - calloc.free(pointer); - calloc.free(data); - } - - @override - void run() { - doStorePointer(pointer, N, data); - final int x = doLoadPointer(pointer, N); - if (x != 0 || x == data.address) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -class PointerInt64Mint extends BenchmarkBase { - Pointer pointer; - PointerInt64Mint() : super('FfiMemory.PointerInt64Mint'); - - @override - void setup() => pointer = calloc(N); - @override - void teardown() => calloc.free(pointer); - - @override - void run() { - doStoreInt64Mint(pointer, N); - final int x = doLoadInt64Mint(pointer, N); - // Using overflow semantics in aggregation. - if (x != -N) { - throw Exception('$name: Unexpected result: $x'); - } - } -} - -// -// Main driver. -// - -void main() { - final benchmarks = [ - () => PointerInt8(), - () => PointerInt8TypedDataNew(), - () => PointerInt8TypedDataReuse(), - () => PointerUint8(), - () => PointerInt16(), - () => PointerUint16(), - () => PointerInt32(), - () => PointerUint32(), - () => PointerUint32Unaligned(), - () => PointerInt64(), - () => PointerInt64Mint(), - () => PointerUint64(), - () => PointerUintPtr(), - () => PointerFloat(), - () => PointerDouble(), - () => PointerPointer(), - ]; - for (final benchmark in benchmarks) { - benchmark().report(); - } -} diff --git a/benchmarks/FfiStruct/dart/FfiStruct.dart b/benchmarks/FfiStruct/dart/FfiStruct.dart index ced6243701c..dad52fa31b3 100644 --- a/benchmarks/FfiStruct/dart/FfiStruct.dart +++ b/benchmarks/FfiStruct/dart/FfiStruct.dart @@ -9,8 +9,8 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; import 'package:benchmark_harness/benchmark_harness.dart'; +import 'package:ffi/ffi.dart'; // // Struct field store (plus Pointer elementAt and load). @@ -68,12 +68,17 @@ class FieldLoadStore extends BenchmarkBase { // Main driver. // -void main() { +void main(List args) { final benchmarks = [ - () => FieldLoadStore(), + FieldLoadStore.new, ]; - for (final benchmark in benchmarks) { - benchmark().report(); + + final filter = args.firstOrNull; + for (var constructor in benchmarks) { + final benchmark = constructor(); + if (filter == null || benchmark.name.contains(filter)) { + benchmark.report(); + } } } diff --git a/benchmarks/FfiStructCopy/dart/FfiStructCopy.dart b/benchmarks/FfiStructCopy/dart/FfiStructCopy.dart index a1967001761..38db2d0c18c 100644 --- a/benchmarks/FfiStructCopy/dart/FfiStructCopy.dart +++ b/benchmarks/FfiStructCopy/dart/FfiStructCopy.dart @@ -10,7 +10,6 @@ import 'dart:ffi'; import 'dart:math'; -import 'package:args/args.dart'; import 'package:ffi/ffi.dart'; import 'benchmark_generated.dart'; @@ -84,26 +83,18 @@ abstract class StructCopyBenchmark { } void main(List args) { - final argParser = ArgParser(); - argParser.addFlag('verbose', abbr: 'v'); - final argsParsed = argParser.parse(args); - final verbose = argsParsed['verbose'] as bool; - final rest = argsParsed.rest; - String? filter; - if (rest.isNotEmpty) { - filter = rest.first; - } - final benchmarks = [ Copy1Bytes.new, Copy32Bytes.new, Copy1024Bytes.new, Copy32768Bytes.new, ]; - for (final benchmark in benchmarks) { - final b = benchmark(); - if (filter == null || b.name.contains(filter)) { - b.report(verbose: verbose); + + final filter = args.firstOrNull; + for (var constructor in benchmarks) { + final benchmark = constructor(); + if (filter == null || benchmark.name.contains(filter)) { + benchmark.report(); } } }