Add AsyncBenchmarkBase.
The async benchmark harness accommodates tests that require async
setup/teardown/run implementations.
diff --git a/lib/benchmark_harness.dart b/lib/benchmark_harness.dart
index 46153a0..2809777 100644
--- a/lib/benchmark_harness.dart
+++ b/lib/benchmark_harness.dart
@@ -4,5 +4,8 @@
library benchmark_harness;
+import 'dart:async';
+
part 'src/benchmark_base.dart';
+part 'src/async_benchmark_base.dart';
part 'src/score_emitter.dart';
diff --git a/lib/src/async_benchmark_base.dart b/lib/src/async_benchmark_base.dart
new file mode 100644
index 0000000..8a020f2
--- /dev/null
+++ b/lib/src/async_benchmark_base.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2014, 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.
+
+part of benchmark_harness;
+
+class AsyncBenchmarkBase {
+ final String name;
+ final ScoreEmitter emitter;
+
+ /// Empty constructor.
+ const AsyncBenchmarkBase(this.name, {this.emitter = const PrintEmitter()});
+
+ /// The benchmark code.
+ ///
+ /// This function is not used, if both [warmup] and [exercise] are
+ /// overwritten.
+ Future<void> run() async {}
+
+ /// Runs a short version of the benchmark. By default invokes [run] once.
+ Future<void> warmup() async {
+ await run();
+ }
+
+ /// Exercises the benchmark. By default invokes [run] once.
+ Future<void> exercise() async {
+ await run();
+ }
+
+ /// Not measured setup code executed prior to the benchmark runs.
+ Future<void> setup() async {}
+
+ /// Not measures teardown code executed after the benchark runs.
+ Future<void> teardown() async {}
+
+ /// Measures the score for this benchmark by executing it repeately until
+ /// time minimum has been reached.
+ static Future<double> measureFor(
+ Future<void> Function() f, int minimumMillis) async {
+ final minimumMicros = minimumMillis * 1000;
+ final watch = Stopwatch()..start();
+ var iter = 0;
+ var elapsed = 0;
+ while (elapsed < minimumMicros) {
+ await f();
+ elapsed = watch.elapsedMicroseconds;
+ iter++;
+ }
+ return elapsed / iter;
+ }
+
+ /// Measures the score for the benchmark and returns it.
+ Future<double> measure() async {
+ await setup();
+ try {
+ // Warmup for at least 100ms. Discard result.
+ await measureFor(warmup, 100);
+ // Run the benchmark for at least 2000ms.
+ return await measureFor(exercise, 2000);
+ } finally {
+ await teardown();
+ }
+ }
+
+ /// Run the benchmark and report results on the [emitter].
+ Future<void> report() async {
+ emitter.emit(name, await measure());
+ }
+}
diff --git a/test/benchmark_harness_test.dart b/test/benchmark_harness_test.dart
index bc85579..eaf0893 100644
--- a/test/benchmark_harness_test.dart
+++ b/test/benchmark_harness_test.dart
@@ -4,14 +4,22 @@
library benchmark_harness_test;
+import 'dart:async';
+
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:test/test.dart';
void main() {
group('benchmark_harness', () {
test('run is called', () {
- var benchmark = MockBenchmark();
- var micros = benchmark.measure();
+ final benchmark = MockBenchmark();
+ final micros = benchmark.measure();
+ expect(micros, isPositive);
+ expect(benchmark.runCount, isPositive);
+ });
+ test('async run is awaited', () async {
+ final benchmark = MockAsyncBenchmark();
+ final micros = await benchmark.measure();
expect(micros, isPositive);
expect(benchmark.runCount, isPositive);
});
@@ -28,3 +36,14 @@
runCount++;
}
}
+
+class MockAsyncBenchmark extends AsyncBenchmarkBase {
+ int runCount = 0;
+ MockAsyncBenchmark() : super('mock benchmark');
+
+ @override
+ Future<void> run() async {
+ await Future<void>.delayed(Duration.zero);
+ runCount++;
+ }
+}