Skip to content

Commit d862279

Browse files
Serve benchmarks with COOP/COEP headers in wasm mode. (#7423)
We need `crossOriginIsolated` for skwasm to work. Otherwise, this just falls back and benchmarks JS + canvaskit.
1 parent 50e4138 commit d862279

File tree

5 files changed

+61
-13
lines changed

5 files changed

+61
-13
lines changed

packages/web_benchmarks/CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
## NEXT
1+
## 2.0.2
22

33
* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3.
4+
* Updates benchmark server to serve the app as `crossOriginIsolated`. This
5+
allows us access to high precision timers and allows wasm benchmarks to run
6+
properly as well.
47

58
## 2.0.1
69

packages/web_benchmarks/lib/src/runner.dart

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,26 @@ class BenchmarkServer {
160160
Cascade cascade = Cascade();
161161

162162
// Serves the static files built for the app (html, js, images, fonts, etc)
163-
cascade = cascade.add(createStaticHandler(
163+
final Handler buildFolderHandler = createStaticHandler(
164164
path.join(benchmarkAppDirectory.path, 'build', 'web'),
165165
defaultDocument: 'index.html',
166-
));
166+
);
167+
// We want our page to be crossOriginIsolated. This will allow us to run the
168+
// skwasm renderer, which uses a SharedArrayBuffer, which requires the page
169+
// to be crossOriginIsolated. But also, even in the non-skwasm case, running
170+
// in crossOriginIsolated gives us access to more accurate timers which are
171+
// useful for capturing good benchmarking data.
172+
// See https://developer.mozilla.org/en-US/docs/Web/API/Performance_API/High_precision_timing#reduced_precision
173+
cascade = cascade.add((Request request) async {
174+
final Response response = await buildFolderHandler(request);
175+
if (response.mimeType == 'text/html') {
176+
return response.change(headers: <String, String>{
177+
'Cross-Origin-Opener-Policy': 'same-origin',
178+
'Cross-Origin-Embedder-Policy': 'require-corp',
179+
});
180+
}
181+
return response;
182+
});
167183

168184
// Serves the benchmark server API used by the benchmark app to coordinate
169185
// the running of benchmarks.

packages/web_benchmarks/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: web_benchmarks
22
description: A benchmark harness for performance-testing Flutter apps in Chrome.
33
repository: https://github.com/flutter/packages/tree/main/packages/web_benchmarks
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+web_benchmarks%22
5-
version: 2.0.1
5+
version: 2.0.2
66

77
environment:
88
sdk: ^3.3.0

packages/web_benchmarks/testing/test_app/lib/benchmarks/runner_simple.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'package:flutter/foundation.dart';
56
import 'package:flutter_test/flutter_test.dart';
67
import 'package:web_benchmarks/client.dart';
78

@@ -12,7 +13,11 @@ class SimpleRecorder extends AppRecorder {
1213

1314
@override
1415
Future<void> automate() async {
15-
// Do nothing.
16+
// Record whether we are in wasm mode or not. Ideally, we'd have a more
17+
// first-class way to add metadata like this, but this will work for us to
18+
// pass information about the environment back to the server for the
19+
// purposes of our own tests.
20+
profile.extraData['isWasm'] = kIsWasm ? 1 : 0;
1621
}
1722
}
1823

packages/web_benchmarks/testing/web_benchmarks_test.dart

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,45 @@ Future<void> main() async {
1919
}, timeout: Timeout.none);
2020

2121
test('Can run a web benchmark with an alternate initial page', () async {
22-
await _runBenchmarks(
22+
final BenchmarkResults results = await _runBenchmarks(
2323
benchmarkNames: <String>['simple'],
2424
entryPoint: 'lib/benchmarks/runner_simple.dart',
2525
initialPage: 'index.html#about',
2626
);
27+
28+
// The simple runner just puts an `isWasm` metric in there so we can make
29+
// sure that we're running in the right environment.
30+
final List<BenchmarkScore>? scores = results.scores['simple'];
31+
expect(scores, isNotNull);
32+
33+
final BenchmarkScore isWasmScore =
34+
scores!.firstWhere((BenchmarkScore score) => score.metric == 'isWasm');
35+
expect(isWasmScore.value, 0);
2736
}, timeout: Timeout.none);
2837

2938
test(
3039
'Can run a web benchmark with wasm',
3140
() async {
32-
await _runBenchmarks(
41+
final BenchmarkResults results = await _runBenchmarks(
3342
benchmarkNames: <String>['simple'],
3443
entryPoint: 'lib/benchmarks/runner_simple.dart',
3544
compilationOptions: const CompilationOptions.wasm(),
3645
);
46+
47+
// The simple runner just puts an `isWasm` metric in there so we can make
48+
// sure that we're running in the right environment.
49+
final List<BenchmarkScore>? scores = results.scores['simple'];
50+
expect(scores, isNotNull);
51+
52+
final BenchmarkScore isWasmScore = scores!
53+
.firstWhere((BenchmarkScore score) => score.metric == 'isWasm');
54+
expect(isWasmScore.value, 1);
3755
},
3856
timeout: Timeout.none,
3957
);
4058
}
4159

42-
Future<void> _runBenchmarks({
60+
Future<BenchmarkResults> _runBenchmarks({
4361
required List<String> benchmarkNames,
4462
required String entryPoint,
4563
String initialPage = defaultInitialPage,
@@ -53,12 +71,17 @@ Future<void> _runBenchmarks({
5371
compilationOptions: compilationOptions,
5472
);
5573

74+
// The skwasm renderer doesn't have preroll or apply frame steps in its rendering.
75+
final List<String> expectedMetrics = compilationOptions.useWasm
76+
? <String>['drawFrameDuration']
77+
: <String>[
78+
'preroll_frame',
79+
'apply_frame',
80+
'drawFrameDuration',
81+
];
82+
5683
for (final String benchmarkName in benchmarkNames) {
57-
for (final String metricName in <String>[
58-
'preroll_frame',
59-
'apply_frame',
60-
'drawFrameDuration',
61-
]) {
84+
for (final String metricName in expectedMetrics) {
6285
for (final String valueName in <String>[
6386
'average',
6487
'outlierAverage',
@@ -83,4 +106,5 @@ Future<void> _runBenchmarks({
83106
const JsonEncoder.withIndent(' ').convert(taskResult.toJson()),
84107
isA<String>(),
85108
);
109+
return taskResult;
86110
}

0 commit comments

Comments
 (0)