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)
This commit is contained in:
John McDole
2024-09-03 09:10:13 -07:00
committed by GitHub
parent 6a47cdb6b5
commit 95c3292623
3 changed files with 58 additions and 3 deletions

View File

@@ -7,6 +7,19 @@ window to see the device logs, then, in a different window, run:
flutter run -d $DEVICE_ID --profile lib/benchmark_collection.dart
```
To run a subset of tests:
```shell
flutter run -d $DEVICE_ID --profile lib/benchmark_collection.dart --dart-define=tests=foundation/change_notifier_bench.dart,language/sync_star_bench.dart
```
To specify a seed value for shuffling tests:
```shell
flutter run -d $DEVICE_ID --profile lib/benchmark_collection.dart --dart-define=seed=12345
```
The results should be in the device logs.
## Avoid changing names of the benchmarks

View File

@@ -3,7 +3,9 @@
// found in the LICENSE file.
import 'dart:io';
import 'dart:math';
import 'package:args/args.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_test/flutter_test.dart';
@@ -93,9 +95,44 @@ Future<void> main() async {
),
];
print('╡ ••• Running microbenchmarks ••• ╞');
// Parses the optional compile-time dart variables; we can't have
// arguments passed in to main.
final ArgParser parser = ArgParser();
final List<String> allowed = benchmarks.map((Benchmark e) => e.$1).toList();
parser.addMultiOption(
'tests',
abbr: 't',
defaultsTo: allowed,
allowed: allowed,
help: 'selected tests to run',
);
parser.addOption(
'seed',
defaultsTo: '12345',
help: 'selects seed to sort tests by',
);
final List<String> mainArgs = <String>[];
const String testArgs = String.fromEnvironment('tests');
if (testArgs.isNotEmpty) {
mainArgs.addAll(<String>['--tests', testArgs]);
print('╡ ••• environment test override: $testArgs ••• ╞');
}
const String seedArgs = String.fromEnvironment('seed');
if (seedArgs.isNotEmpty) {
mainArgs.addAll(<String>['--seed', seedArgs]);
print('╡ ••• environment seed override: $seedArgs ••• ╞');
}
final ArgResults results = parser.parse(mainArgs);
final List<String> selectedTests = results.multiOption('tests');
for (final Benchmark mark in benchmarks) {
// Shuffle the tests becauase we don't want order dependent tests.
// It is the responsibily of the infra to tell us what the seed value is,
// in case we want to have the seed stable for some time period.
final List<Benchmark> tests = benchmarks.where((Benchmark e) => selectedTests.contains(e.$1)).toList();
tests.shuffle(Random(int.parse(results.option('seed')!)));
print('╡ ••• Running microbenchmarks ••• ╞');
for (final Benchmark mark in tests) {
// Reset the frame policy to default - each test can set it on their own.
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fadePointers;
print('╡ ••• Running ${mark.$1} ••• ╞');

View File

@@ -19,6 +19,10 @@ TaskFunction createMicrobenchmarkTask({
bool? enableImpeller,
Map<String, String> environment = const <String, String>{},
}) {
// Generate a seed for this test stable around the date.
final int seed = DateTime.now().toUtc().subtract(const Duration(hours: 7)).hashCode;
return () async {
final Device device = await devices.workingDevice;
await device.unlock();
@@ -43,7 +47,7 @@ TaskFunction createMicrobenchmarkTask({
Future<Map<String, double>> runMicrobench(String benchmarkPath) async {
Future<Map<String, double>> run() async {
print('Running $benchmarkPath');
print('Running $benchmarkPath with seed $seed');
final Process flutterProcess = await inDirectory(appDir, () async {
final List<String> options = <String>[
@@ -55,6 +59,7 @@ TaskFunction createMicrobenchmarkTask({
if (enableImpeller != null && !enableImpeller) '--no-enable-impeller',
'-d',
device.deviceId,
'--dart-define=seed=$seed',
benchmarkPath,
];
return startFlutter(