Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serve benchmarks with COOP/COEP headers in wasm mode. #7423

Merged
merged 4 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/web_benchmarks/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
## NEXT
## 2.0.2

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

## 2.0.1

Expand Down
20 changes: 18 additions & 2 deletions packages/web_benchmarks/lib/src/runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,26 @@ class BenchmarkServer {
Cascade cascade = Cascade();

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

// Serves the benchmark server API used by the benchmark app to coordinate
// the running of benchmarks.
Expand Down
2 changes: 1 addition & 1 deletion packages/web_benchmarks/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: web_benchmarks
description: A benchmark harness for performance-testing Flutter apps in Chrome.
repository: https://github.com/flutter/packages/tree/main/packages/web_benchmarks
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+web_benchmarks%22
version: 2.0.1
version: 2.0.2

environment:
sdk: ^3.3.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:web_benchmarks/client.dart';

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

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

Expand Down
40 changes: 32 additions & 8 deletions packages/web_benchmarks/testing/web_benchmarks_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,45 @@ Future<void> main() async {
}, timeout: Timeout.none);

test('Can run a web benchmark with an alternate initial page', () async {
await _runBenchmarks(
final BenchmarkResults results = await _runBenchmarks(
benchmarkNames: <String>['simple'],
entryPoint: 'lib/benchmarks/runner_simple.dart',
initialPage: 'index.html#about',
);

// The simple runner just puts an `isWasm` metric in there so we can make
// sure that we're running in the right environment.
final List<BenchmarkScore>? scores = results.scores['simple'];
expect(scores, isNotNull);

final BenchmarkScore isWasmScore =
scores!.firstWhere((BenchmarkScore score) => score.metric == 'isWasm');
expect(isWasmScore.value, 0);
}, timeout: Timeout.none);

test(
'Can run a web benchmark with wasm',
() async {
await _runBenchmarks(
final BenchmarkResults results = await _runBenchmarks(
benchmarkNames: <String>['simple'],
entryPoint: 'lib/benchmarks/runner_simple.dart',
compilationOptions: const CompilationOptions.wasm(),
);

// The simple runner just puts an `isWasm` metric in there so we can make
// sure that we're running in the right environment.
final List<BenchmarkScore>? scores = results.scores['simple'];
expect(scores, isNotNull);

final BenchmarkScore isWasmScore = scores!
.firstWhere((BenchmarkScore score) => score.metric == 'isWasm');
expect(isWasmScore.value, 1);
},
timeout: Timeout.none,
);
}

Future<void> _runBenchmarks({
Future<BenchmarkResults> _runBenchmarks({
required List<String> benchmarkNames,
required String entryPoint,
String initialPage = defaultInitialPage,
Expand All @@ -53,12 +71,17 @@ Future<void> _runBenchmarks({
compilationOptions: compilationOptions,
);

// The skwasm renderer doesn't have preroll or apply frame steps in its rendering.
final List<String> expectedMetrics = compilationOptions.useWasm
? <String>['drawFrameDuration']
: <String>[
'preroll_frame',
'apply_frame',
'drawFrameDuration',
];

for (final String benchmarkName in benchmarkNames) {
for (final String metricName in <String>[
'preroll_frame',
'apply_frame',
'drawFrameDuration',
]) {
for (final String metricName in expectedMetrics) {
for (final String valueName in <String>[
'average',
'outlierAverage',
Expand All @@ -83,4 +106,5 @@ Future<void> _runBenchmarks({
const JsonEncoder.withIndent(' ').convert(taskResult.toJson()),
isA<String>(),
);
return taskResult;
}