|  | // 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:ffi/ffi.dart'; | 
|  | import 'package:benchmark_harness/benchmark_harness.dart'; | 
|  |  | 
|  | // | 
|  | // Struct field store (plus Pointer elementAt and load). | 
|  | // | 
|  |  | 
|  | void doStoreInt32(Pointer<VeryLargeStruct> 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<VeryLargeStruct> 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<VeryLargeStruct> 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() { | 
|  | final benchmarks = [ | 
|  | () => FieldLoadStore(), | 
|  | ]; | 
|  | for (final benchmark in benchmarks) { | 
|  | benchmark().report(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // | 
|  | // Test struct. | 
|  | // | 
|  | 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<VeryLargeStruct> parent; | 
|  |  | 
|  | @IntPtr() | 
|  | external int numChildren; | 
|  |  | 
|  | external Pointer<VeryLargeStruct> children; | 
|  |  | 
|  | @Int8() | 
|  | external int smallLastField; | 
|  | } |