Add --local-web-sdk in devicelab runner to make --ab testing work for web (#123825)
This allows us to check for performance differences in local Web SDKs.
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-new channel
on [Discord].
<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
diff --git a/dev/devicelab/bin/run.dart b/dev/devicelab/bin/run.dart
index 25da577..1a13762 100644
--- a/dev/devicelab/bin/run.dart
+++ b/dev/devicelab/bin/run.dart
@@ -38,6 +38,11 @@
/// Required for A/B test mode.
final String? localEngine = args['local-engine'] as String?;
+ /// The build of the local Web SDK to use.
+ ///
+ /// Required for A/B test mode.
+ final String? localWebSdk = args['local-web-sdk'] as String?;
+
/// The path to the engine "src/" directory.
final String? localEngineSrcPath = args['local-engine-src-path'] as String?;
@@ -85,8 +90,8 @@
stderr.writeln(argParser.usage);
exit(1);
}
- if (localEngine == null) {
- stderr.writeln('When running in A/B test mode --local-engine is required.\n');
+ if (localEngine == null && localWebSdk == null) {
+ stderr.writeln('When running in A/B test mode --local-engine or --local-web-sdk is required.\n');
stderr.writeln(argParser.usage);
exit(1);
}
@@ -94,6 +99,7 @@
runsPerTest: runsPerTest,
silent: silent,
localEngine: localEngine,
+ localWebSdk: localWebSdk,
localEngineSrcPath: localEngineSrcPath,
deviceId: deviceId,
resultsFile: resultsFile,
@@ -118,7 +124,8 @@
Future<void> _runABTest({
required int runsPerTest,
required bool silent,
- required String localEngine,
+ required String? localEngine,
+ required String? localWebSdk,
required String? localEngineSrcPath,
required String? deviceId,
required String resultsFile,
@@ -126,7 +133,9 @@
}) async {
print('$taskName A/B test. Will run $runsPerTest times.');
- final ABTest abTest = ABTest(localEngine, taskName);
+ assert(localEngine != null || localWebSdk != null);
+
+ final ABTest abTest = ABTest((localEngine ?? localWebSdk)!, taskName);
for (int i = 1; i <= runsPerTest; i++) {
section('Run #$i');
@@ -152,6 +161,7 @@
taskName,
silent: silent,
localEngine: localEngine,
+ localWebSdk: localWebSdk,
localEngineSrcPath: localEngineSrcPath,
deviceId: deviceId,
);
@@ -282,6 +292,14 @@
'This path is relative to --local-engine-src-path/out. This option\n'
'is required when running an A/B test (see the --ab option).',
)
+ ..addOption(
+ 'local-web-sdk',
+ help: 'Name of a build output within the engine out directory, if you\n'
+ 'are building Flutter locally. Use this to select a specific\n'
+ 'version of the engine if you have built multiple engine targets.\n'
+ 'This path is relative to --local-engine-src-path/out. This option\n'
+ 'is required when running an A/B test (see the --ab option).',
+ )
..addFlag(
'list',
abbr: 'l',
diff --git a/dev/devicelab/lib/framework/runner.dart b/dev/devicelab/lib/framework/runner.dart
index 0a8368f..88a81d8 100644
--- a/dev/devicelab/lib/framework/runner.dart
+++ b/dev/devicelab/lib/framework/runner.dart
@@ -153,6 +153,7 @@
bool terminateStrayDartProcesses = false,
bool silent = false,
String? localEngine,
+ String? localWebSdk,
String? localEngineSrcPath,
String? deviceId,
List<String>? taskArgs,
@@ -181,6 +182,7 @@
'--enable-vm-service=0', // zero causes the system to choose a free port
'--no-pause-isolates-on-exit',
if (localEngine != null) '-DlocalEngine=$localEngine',
+ if (localWebSdk != null) '-DlocalWebSdk=$localWebSdk',
if (localEngineSrcPath != null) '-DlocalEngineSrcPath=$localEngineSrcPath',
taskExecutable,
...?taskArgs,
diff --git a/dev/devicelab/lib/framework/utils.dart b/dev/devicelab/lib/framework/utils.dart
index 493d1f3..ad057e3 100644
--- a/dev/devicelab/lib/framework/utils.dart
+++ b/dev/devicelab/lib/framework/utils.dart
@@ -35,6 +35,14 @@
return isDefined ? const String.fromEnvironment('localEngineSrcPath') : null;
}
+/// The local Web SDK to use for [flutter] and [evalFlutter], if any.
+///
+/// This is set as an environment variable when running the task, see runTask in runner.dart.
+String? get localWebSdkFromEnv {
+ const bool isDefined = bool.hasEnvironment('localWebSdk');
+ return isDefined ? const String.fromEnvironment('localWebSdk') : null;
+}
+
List<ProcessInfo> _runningProcesses = <ProcessInfo>[];
ProcessManager _processManager = const LocalProcessManager();
@@ -446,6 +454,7 @@
};
final String? localEngine = localEngineFromEnv;
final String? localEngineSrcPath = localEngineSrcPathFromEnv;
+ final String? localWebSdk = localWebSdkFromEnv;
return <String>[
command,
if (deviceOperatingSystem == DeviceOperatingSystem.ios && supportedDeviceTimeoutCommands.contains(command))
@@ -460,6 +469,7 @@
],
if (localEngine != null) ...<String>['--local-engine', localEngine],
if (localEngineSrcPath != null) ...<String>['--local-engine-src-path', localEngineSrcPath],
+ if (localWebSdk != null) ...<String>['--local-web-sdk', localWebSdk],
...options,
];
}
diff --git a/dev/devicelab/lib/tasks/perf_tests.dart b/dev/devicelab/lib/tasks/perf_tests.dart
index f0fd4bd..b3bdfb1 100644
--- a/dev/devicelab/lib/tasks/perf_tests.dart
+++ b/dev/devicelab/lib/tasks/perf_tests.dart
@@ -1192,6 +1192,7 @@
return inDirectory<Map<String, int>>(directory, () async {
final Map<String, int> metrics = <String, int>{};
+ await flutter('clean');
await flutter('packages', options: <String>['get']);
final Stopwatch? watch = measureBuildTime ? Stopwatch() : null;
watch?.start();
@@ -1200,6 +1201,7 @@
'-v',
'--release',
'--no-pub',
+ '--no-web-resources-cdn',
]);
watch?.stop();
final String buildDir = path.join(directory, 'build', 'web');
diff --git a/dev/devicelab/lib/tasks/web_benchmarks.dart b/dev/devicelab/lib/tasks/web_benchmarks.dart
index 3a1938f..d3defb4 100644
--- a/dev/devicelab/lib/tasks/web_benchmarks.dart
+++ b/dev/devicelab/lib/tasks/web_benchmarks.dart
@@ -25,11 +25,13 @@
Logger.root.level = Level.INFO;
final String macrobenchmarksDirectory = path.join(flutterDirectory.path, 'dev', 'benchmarks', 'macrobenchmarks');
return inDirectory(macrobenchmarksDirectory, () async {
+ await flutter('clean');
await evalFlutter('build', options: <String>[
'web',
'--dart-define=FLUTTER_WEB_ENABLE_PROFILING=true',
'--web-renderer=${useCanvasKit ? 'canvaskit' : 'html'}',
'--profile',
+ '--no-web-resources-cdn',
'-t',
'lib/web_benchmarks.dart',
]);