diff --git a/pkgs/benchmark_harness/CHANGELOG.md b/pkgs/benchmark_harness/CHANGELOG.md index fceecb830..f0e24bf7e 100644 --- a/pkgs/benchmark_harness/CHANGELOG.md +++ b/pkgs/benchmark_harness/CHANGELOG.md @@ -1,3 +1,5 @@ +## 2.3.2-wip + ## 2.3.1 - Move to `dart-lang/tools` monorepo. diff --git a/pkgs/benchmark_harness/lib/src/benchmark_base.dart b/pkgs/benchmark_harness/lib/src/benchmark_base.dart index bc874f54a..d119d4da2 100644 --- a/pkgs/benchmark_harness/lib/src/benchmark_base.dart +++ b/pkgs/benchmark_harness/lib/src/benchmark_base.dart @@ -2,8 +2,7 @@ // 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. -import 'dart:math' as math; - +import 'measurement.dart'; import 'score_emitter.dart'; const int minimumMeasureDurationMillis = 2000; @@ -61,53 +60,3 @@ class BenchmarkBase { emitter.emit(name, measure()); } } - -/// Measures the score for this benchmark by executing it enough times -/// to reach [minimumMillis]. -Measurement measureForImpl(void Function() f, int minimumMillis) { - final minimumMicros = minimumMillis * 1000; - // If running a long measurement permit some amount of measurement jitter - // to avoid discarding results that are almost good, but not quite there. - final allowedJitter = - minimumMillis < 1000 ? 0 : (minimumMicros * 0.1).floor(); - var iter = 2; - var totalIterations = iter; - final watch = Stopwatch()..start(); - while (true) { - watch.reset(); - for (var i = 0; i < iter; i++) { - f(); - } - final elapsed = watch.elapsedMicroseconds; - final measurement = Measurement(elapsed, iter, totalIterations); - if (measurement.elapsedMicros >= (minimumMicros - allowedJitter)) { - return measurement; - } - - iter = measurement.estimateIterationsNeededToReach( - minimumMicros: minimumMicros); - totalIterations += iter; - } -} - -class Measurement { - final int elapsedMicros; - final int iterations; - final int totalIterations; - - Measurement(this.elapsedMicros, this.iterations, this.totalIterations); - - double get score => elapsedMicros / iterations; - - int estimateIterationsNeededToReach({required int minimumMicros}) { - final elapsed = roundDownToMillisecond(elapsedMicros); - return elapsed == 0 - ? iterations * 1000 - : (iterations * math.max(minimumMicros / elapsed, 1.5)).ceil(); - } - - static int roundDownToMillisecond(int micros) => (micros ~/ 1000) * 1000; - - @override - String toString() => '$elapsedMicros in $iterations iterations'; -} diff --git a/pkgs/benchmark_harness/lib/src/measurement.dart b/pkgs/benchmark_harness/lib/src/measurement.dart new file mode 100644 index 000000000..11119b983 --- /dev/null +++ b/pkgs/benchmark_harness/lib/src/measurement.dart @@ -0,0 +1,57 @@ +// Copyright (c) 2025, 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. + +import 'dart:math' as math; + +/// Measures the score for this benchmark by executing it enough times +/// to reach [minimumMillis]. +/// +/// [f] will be run a minimum of 2 times. +Measurement measureForImpl(void Function() f, int minimumMillis) { + final minimumMicros = minimumMillis * 1000; + // If running a long measurement permit some amount of measurement jitter + // to avoid discarding results that are almost good, but not quite there. + final allowedJitter = + minimumMillis < 1000 ? 0 : (minimumMicros * 0.1).floor(); + var iter = 2; + var totalIterations = iter; + final watch = Stopwatch()..start(); + while (true) { + watch.reset(); + for (var i = 0; i < iter; i++) { + f(); + } + final elapsed = watch.elapsedMicroseconds; + final measurement = Measurement(elapsed, iter, totalIterations); + if (measurement.elapsedMicros >= (minimumMicros - allowedJitter)) { + return measurement; + } + + iter = measurement.estimateIterationsNeededToReach( + minimumMicros: minimumMicros); + totalIterations += iter; + } +} + +class Measurement { + Measurement(this.elapsedMicros, this.iterations, this.totalIterations); + + final int elapsedMicros; + final int iterations; + final int totalIterations; + + double get score => elapsedMicros / iterations; + + int estimateIterationsNeededToReach({required int minimumMicros}) { + final elapsed = _roundDownToMillisecond(elapsedMicros); + return elapsed == 0 + ? iterations * 1000 + : (iterations * math.max(minimumMicros / elapsed, 1.5)).ceil(); + } + + @override + String toString() => '$elapsedMicros in $iterations iterations'; +} + +int _roundDownToMillisecond(int micros) => (micros ~/ 1000) * 1000; diff --git a/pkgs/benchmark_harness/lib/src/perf_benchmark_base.dart b/pkgs/benchmark_harness/lib/src/perf_benchmark_base.dart index 1b7fb92a1..a1c3de9c9 100644 --- a/pkgs/benchmark_harness/lib/src/perf_benchmark_base.dart +++ b/pkgs/benchmark_harness/lib/src/perf_benchmark_base.dart @@ -7,6 +7,7 @@ import 'dart:convert'; import 'dart:io'; import 'benchmark_base.dart'; +import 'measurement.dart'; import 'score_emitter.dart'; class PerfBenchmarkBase extends BenchmarkBase { diff --git a/pkgs/benchmark_harness/pubspec.yaml b/pkgs/benchmark_harness/pubspec.yaml index d9b82e5fb..8561c2a06 100644 --- a/pkgs/benchmark_harness/pubspec.yaml +++ b/pkgs/benchmark_harness/pubspec.yaml @@ -1,5 +1,5 @@ name: benchmark_harness -version: 2.3.1 +version: 2.3.2-wip description: The official Dart project benchmark harness. repository: https://github.com/dart-lang/tools/tree/main/pkgs/benchmark_harness issue_tracker: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Abenchmark_harness