Skip to content

Commit 95c3292

Browse files
authored
Improve microbenchmarks a smidge (#154461)
1. Allow for selective benchmarks to run locally (see README.md) 2. Shuffle the tests; the seed being rotated daily or specified (see README.md)
1 parent 6a47cdb commit 95c3292

File tree

3 files changed

+58
-3
lines changed

3 files changed

+58
-3
lines changed

dev/benchmarks/microbenchmarks/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@ window to see the device logs, then, in a different window, run:
77
flutter run -d $DEVICE_ID --profile lib/benchmark_collection.dart
88
```
99

10+
To run a subset of tests:
11+
12+
```shell
13+
flutter run -d $DEVICE_ID --profile lib/benchmark_collection.dart --dart-define=tests=foundation/change_notifier_bench.dart,language/sync_star_bench.dart
14+
```
15+
16+
To specify a seed value for shuffling tests:
17+
18+
```shell
19+
flutter run -d $DEVICE_ID --profile lib/benchmark_collection.dart --dart-define=seed=12345
20+
```
21+
22+
1023
The results should be in the device logs.
1124

1225
## Avoid changing names of the benchmarks

dev/benchmarks/microbenchmarks/lib/benchmark_collection.dart

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
// found in the LICENSE file.
44

55
import 'dart:io';
6+
import 'dart:math';
67

8+
import 'package:args/args.dart';
79
import 'package:flutter/material.dart';
810
import 'package:flutter/scheduler.dart';
911
import 'package:flutter_test/flutter_test.dart';
@@ -93,9 +95,44 @@ Future<void> main() async {
9395
),
9496
];
9597

96-
print('╡ ••• Running microbenchmarks ••• ╞');
98+
// Parses the optional compile-time dart variables; we can't have
99+
// arguments passed in to main.
100+
final ArgParser parser = ArgParser();
101+
final List<String> allowed = benchmarks.map((Benchmark e) => e.$1).toList();
102+
parser.addMultiOption(
103+
'tests',
104+
abbr: 't',
105+
defaultsTo: allowed,
106+
allowed: allowed,
107+
help: 'selected tests to run',
108+
);
109+
parser.addOption(
110+
'seed',
111+
defaultsTo: '12345',
112+
help: 'selects seed to sort tests by',
113+
);
114+
final List<String> mainArgs = <String>[];
115+
const String testArgs = String.fromEnvironment('tests');
116+
if (testArgs.isNotEmpty) {
117+
mainArgs.addAll(<String>['--tests', testArgs]);
118+
print('╡ ••• environment test override: $testArgs ••• ╞');
119+
}
120+
const String seedArgs = String.fromEnvironment('seed');
121+
if (seedArgs.isNotEmpty) {
122+
mainArgs.addAll(<String>['--seed', seedArgs]);
123+
print('╡ ••• environment seed override: $seedArgs ••• ╞');
124+
}
125+
final ArgResults results = parser.parse(mainArgs);
126+
final List<String> selectedTests = results.multiOption('tests');
97127

98-
for (final Benchmark mark in benchmarks) {
128+
// Shuffle the tests becauase we don't want order dependent tests.
129+
// It is the responsibily of the infra to tell us what the seed value is,
130+
// in case we want to have the seed stable for some time period.
131+
final List<Benchmark> tests = benchmarks.where((Benchmark e) => selectedTests.contains(e.$1)).toList();
132+
tests.shuffle(Random(int.parse(results.option('seed')!)));
133+
134+
print('╡ ••• Running microbenchmarks ••• ╞');
135+
for (final Benchmark mark in tests) {
99136
// Reset the frame policy to default - each test can set it on their own.
100137
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fadePointers;
101138
print('╡ ••• Running ${mark.$1} ••• ╞');

dev/devicelab/lib/tasks/microbenchmarks.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ TaskFunction createMicrobenchmarkTask({
1919
bool? enableImpeller,
2020
Map<String, String> environment = const <String, String>{},
2121
}) {
22+
23+
// Generate a seed for this test stable around the date.
24+
final int seed = DateTime.now().toUtc().subtract(const Duration(hours: 7)).hashCode;
25+
2226
return () async {
2327
final Device device = await devices.workingDevice;
2428
await device.unlock();
@@ -43,7 +47,7 @@ TaskFunction createMicrobenchmarkTask({
4347

4448
Future<Map<String, double>> runMicrobench(String benchmarkPath) async {
4549
Future<Map<String, double>> run() async {
46-
print('Running $benchmarkPath');
50+
print('Running $benchmarkPath with seed $seed');
4751

4852
final Process flutterProcess = await inDirectory(appDir, () async {
4953
final List<String> options = <String>[
@@ -55,6 +59,7 @@ TaskFunction createMicrobenchmarkTask({
5559
if (enableImpeller != null && !enableImpeller) '--no-enable-impeller',
5660
'-d',
5761
device.deviceId,
62+
'--dart-define=seed=$seed',
5863
benchmarkPath,
5964
];
6065
return startFlutter(

0 commit comments

Comments
 (0)