Files
sdk/benchmarks/FfiStructCopy/dart/FfiStructCopy.dart
T
Daco Harkes 4af8469493 [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 <sortie@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
2023-05-09 09:50:24 +00:00

101 lines
2.7 KiB
Dart

// Copyright (c) 2022, 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-benchmarks for ffi memory copies.
//
// These micro benchmarks track the speed of doing mem-copies when copying
// structs.
import 'dart:ffi';
import 'dart:math';
import 'package:ffi/ffi.dart';
import 'benchmark_generated.dart';
abstract class StructCopyBenchmark {
final String name;
StructCopyBenchmark(this.name);
int get copySizeInBytes;
Pointer get from;
Pointer get to;
static const targetBatchSizeInBytes = 32 * 1024;
late final int batchSize = max(targetBatchSizeInBytes ~/ copySizeInBytes, 1);
// Returns the number of bytes copied per second.
double measureFor(Duration duration) {
// Prevent `sw.elapsedMicroseconds` from dominating with maps with a
// small number of elements.
final int batchSizeInBytes = batchSize * copySizeInBytes;
int numberOfBytesCopied = 0;
int totalMicroseconds = 0;
final sw = Stopwatch()..start();
final durationInMicroseconds = duration.inMicroseconds;
do {
run(batchSize);
numberOfBytesCopied += batchSizeInBytes;
totalMicroseconds = sw.elapsedMicroseconds;
} while (totalMicroseconds < durationInMicroseconds);
const microsecondsInSecond = 1000 * 1000;
return numberOfBytesCopied * microsecondsInSecond / totalMicroseconds;
}
// Runs warmup phase, runs benchmark and reports result.
void report({bool verbose = false}) {
setup(batchSize);
// Warmup for 100 ms.
measureFor(const Duration(milliseconds: 100));
// Run benchmark for 2 seconds.
final double bytesPerSecond = measureFor(const Duration(seconds: 2));
// Report result.
print('$name(BytesPerSecond): $bytesPerSecond');
if (verbose) {
const nanoSecondsPerSecond = 1000 * 1000 * 1000;
final nanosecondsPerByte = nanoSecondsPerSecond / bytesPerSecond;
print('$name(NanosecondsPerChar): $nanosecondsPerByte');
const bytesPerMegaByte = 1024 * 1024;
final mbPerSecond = bytesPerSecond / bytesPerMegaByte;
print('$name: $mbPerSecond MB per second copied.');
}
teardown();
}
void teardown() {
calloc.free(from);
calloc.free(to);
}
void setup(int batchSize);
void run(int batchSize);
}
void main(List<String> args) {
final benchmarks = [
Copy1Bytes.new,
Copy32Bytes.new,
Copy1024Bytes.new,
Copy32768Bytes.new,
];
final filter = args.firstOrNull;
for (var constructor in benchmarks) {
final benchmark = constructor();
if (filter == null || benchmark.name.contains(filter)) {
benchmark.report();
}
}
}