// 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. // Micro-benchmark for ffi struct field stores and loads. // // Only tests a single field because the FfiMemory benchmark already tests loads // and stores of different field sizes. import 'dart:ffi'; import 'package:benchmark_harness/benchmark_harness.dart'; import 'package:ffi/ffi.dart'; // // Struct field store (plus Pointer elementAt and load). // void doStoreInt32(Pointer pointer, int length) { for (int i = 0; i < length; i++) { pointer[i].c = 1; } } // // Struct field load (plus Pointer elementAt and load). // int doLoadInt32(Pointer pointer, int length) { int x = 0; for (int i = 0; i < length; i++) { x += pointer[i].c; } return x; } // // Benchmark fixture. // // Number of repeats: 1000 // * CPU: Intel(R) Xeon(R) Gold 6154 // * Architecture: x64 // * 150000 - 465000 us (without optimizations) // * 14 - ??? us (expected with optimizations, on par with typed data) const N = 1000; class FieldLoadStore extends BenchmarkBase { Pointer pointer = nullptr; FieldLoadStore() : super('FfiStruct.FieldLoadStore'); @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'); } } } // // Main driver. // void main(List args) { final benchmarks = [ FieldLoadStore.new, ]; final filter = args.firstOrNull; for (var constructor in benchmarks) { final benchmark = constructor(); if (filter == null || benchmark.name.contains(filter)) { benchmark.report(); } } } // // Test struct. // final class VeryLargeStruct extends Struct { @Int8() external int a; @Int16() external int b; @Int32() external int c; @Int64() external int d; @Uint8() external int e; @Uint16() external int f; @Uint32() external int g; @Uint64() external int h; @IntPtr() external int i; @Double() external double j; @Float() external double k; external Pointer parent; @IntPtr() external int numChildren; external Pointer children; @Int8() external int smallLastField; }