[benchmark_harness] Move Measure into its on lib (#2092)

diff --git a/pkgs/benchmark_harness/CHANGELOG.md b/pkgs/benchmark_harness/CHANGELOG.md
index fceecb8..f0e24bf 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 bc874f5..d119d4d 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 @@
     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 0000000..11119b9
--- /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 1b7fb92..a1c3de9 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: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 d9b82e5..8561c2a 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