From 3f6f15722e6e7c7c3f027323f84805c15d20c059 Mon Sep 17 00:00:00 2001 From: Kenzie Schmoll Date: Thu, 7 Dec 2023 11:36:13 -0800 Subject: [PATCH 1/6] Add the ability to run web_benchmarks with Wasm --- packages/web_benchmarks/lib/server.dart | 2 ++ packages/web_benchmarks/lib/src/runner.dart | 11 ++++++++++- .../web_benchmarks/testing/web_benchmarks_test.dart | 10 ++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/web_benchmarks/lib/server.dart b/packages/web_benchmarks/lib/server.dart index 41ae7623ec9..c49456c0bb5 100644 --- a/packages/web_benchmarks/lib/server.dart +++ b/packages/web_benchmarks/lib/server.dart @@ -49,6 +49,7 @@ Future serveWebBenchmark({ bool headless = true, bool treeShakeIcons = true, String initialPage = defaultInitialPage, + bool useWasm = false, }) async { // Reduce logging level. Otherwise, package:webkit_inspection_protocol is way too spammy. Logger.root.level = Level.INFO; @@ -62,5 +63,6 @@ Future serveWebBenchmark({ headless: headless, treeShakeIcons: treeShakeIcons, initialPage: initialPage, + useWasm: useWasm, ).run(); } diff --git a/packages/web_benchmarks/lib/src/runner.dart b/packages/web_benchmarks/lib/src/runner.dart index 9396f42ebc3..cec037eca5c 100644 --- a/packages/web_benchmarks/lib/src/runner.dart +++ b/packages/web_benchmarks/lib/src/runner.dart @@ -55,6 +55,7 @@ class BenchmarkServer { required this.chromeDebugPort, required this.headless, required this.treeShakeIcons, + this.useWasm = false, this.initialPage = defaultInitialPage, }); @@ -75,6 +76,9 @@ class BenchmarkServer { /// Whether to build the app in CanvasKit mode. final bool useCanvasKit; + /// Whether to build the app with dart2wasm. + final bool useWasm; + /// The port this benchmark server serves the app on. final int benchmarkServerPort; @@ -114,8 +118,13 @@ class BenchmarkServer { 'flutter', 'build', 'web', + if (useWasm) ...[ + '--wasm', + '--wasm-opt=debug', + '--omit-type-checks', + ], + if (useCanvasKit) '--web-renderer=canvaskit', '--dart-define=FLUTTER_WEB_ENABLE_PROFILING=true', - if (useCanvasKit) '--dart-define=FLUTTER_WEB_USE_SKIA=true', if (!treeShakeIcons) '--no-tree-shake-icons', '--profile', '-t', diff --git a/packages/web_benchmarks/testing/web_benchmarks_test.dart b/packages/web_benchmarks/testing/web_benchmarks_test.dart index 5d005e2afc7..b76641a6b66 100644 --- a/packages/web_benchmarks/testing/web_benchmarks_test.dart +++ b/packages/web_benchmarks/testing/web_benchmarks_test.dart @@ -25,12 +25,21 @@ Future main() async { initialPage: 'index.html#about', ); }, timeout: Timeout.none); + + test('Can run a web benchmark with wasm', () async { + await _runBenchmarks( + benchmarkNames: ['simple'], + entryPoint: 'lib/benchmarks/runner_simple.dart', + useWasm: true, + ); + }, timeout: Timeout.none); } Future _runBenchmarks({ required List benchmarkNames, required String entryPoint, String initialPage = defaultInitialPage, + bool useWasm = false, }) async { final BenchmarkResults taskResult = await serveWebBenchmark( benchmarkAppDirectory: Directory('testing/test_app'), @@ -38,6 +47,7 @@ Future _runBenchmarks({ useCanvasKit: false, treeShakeIcons: false, initialPage: initialPage, + useWasm: useWasm, ); for (final String benchmarkName in benchmarkNames) { From 6afe4c63787eae5ddb656a2284ec8042b1eaab37 Mon Sep 17 00:00:00 2001 From: Kenzie Schmoll Date: Thu, 7 Dec 2023 11:36:55 -0800 Subject: [PATCH 2/6] Version and changelog --- packages/web_benchmarks/CHANGELOG.md | 4 ++++ packages/web_benchmarks/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/web_benchmarks/CHANGELOG.md b/packages/web_benchmarks/CHANGELOG.md index 9acd4517ab2..9651cddc16a 100644 --- a/packages/web_benchmarks/CHANGELOG.md +++ b/packages/web_benchmarks/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.0+12 + +* Add the ability to run a benchmark with WebAssembly. + ## 0.1.0+11 * Migrates benchmark recorder from `dart:html` to `package:web` to support WebAssembly. diff --git a/packages/web_benchmarks/pubspec.yaml b/packages/web_benchmarks/pubspec.yaml index e9e1791bd75..a07ea54bc06 100644 --- a/packages/web_benchmarks/pubspec.yaml +++ b/packages/web_benchmarks/pubspec.yaml @@ -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: 0.1.0+11 +version: 0.1.0+12 environment: sdk: ">=3.2.0 <4.0.0" From 217d0eb87a2139cfcceb4f588dac2856ff1e96e3 Mon Sep 17 00:00:00 2001 From: Kenzie Schmoll Date: Thu, 7 Dec 2023 12:22:53 -0800 Subject: [PATCH 3/6] use `compilationOptions` --- packages/web_benchmarks/CHANGELOG.md | 3 +- packages/web_benchmarks/lib/server.dart | 6 +-- packages/web_benchmarks/lib/src/runner.dart | 44 +++++++++++++++---- packages/web_benchmarks/pubspec.yaml | 2 +- .../testing/web_benchmarks_test.dart | 8 ++-- 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/packages/web_benchmarks/CHANGELOG.md b/packages/web_benchmarks/CHANGELOG.md index 9651cddc16a..c393626e6a1 100644 --- a/packages/web_benchmarks/CHANGELOG.md +++ b/packages/web_benchmarks/CHANGELOG.md @@ -1,5 +1,6 @@ -## 0.1.0+12 +## 1.0.0 +* **Breaking change:** replace 'useCanvasKit' parameter with 'compilationOptions'. * Add the ability to run a benchmark with WebAssembly. ## 0.1.0+11 diff --git a/packages/web_benchmarks/lib/server.dart b/packages/web_benchmarks/lib/server.dart index c49456c0bb5..c4a51ca5d34 100644 --- a/packages/web_benchmarks/lib/server.dart +++ b/packages/web_benchmarks/lib/server.dart @@ -43,13 +43,12 @@ const int defaultChromeDebugPort = 10000; Future serveWebBenchmark({ required io.Directory benchmarkAppDirectory, required String entryPoint, - required bool useCanvasKit, int benchmarkServerPort = defaultBenchmarkServerPort, int chromeDebugPort = defaultChromeDebugPort, bool headless = true, bool treeShakeIcons = true, String initialPage = defaultInitialPage, - bool useWasm = false, + CompilationOptions compilationOptions = const CompilationOptions(), }) async { // Reduce logging level. Otherwise, package:webkit_inspection_protocol is way too spammy. Logger.root.level = Level.INFO; @@ -57,12 +56,11 @@ Future serveWebBenchmark({ return BenchmarkServer( benchmarkAppDirectory: benchmarkAppDirectory, entryPoint: entryPoint, - useCanvasKit: useCanvasKit, benchmarkServerPort: benchmarkServerPort, chromeDebugPort: chromeDebugPort, headless: headless, + compilationOptions: compilationOptions, treeShakeIcons: treeShakeIcons, initialPage: initialPage, - useWasm: useWasm, ).run(); } diff --git a/packages/web_benchmarks/lib/src/runner.dart b/packages/web_benchmarks/lib/src/runner.dart index cec037eca5c..b8ed072f068 100644 --- a/packages/web_benchmarks/lib/src/runner.dart +++ b/packages/web_benchmarks/lib/src/runner.dart @@ -50,12 +50,11 @@ class BenchmarkServer { BenchmarkServer({ required this.benchmarkAppDirectory, required this.entryPoint, - required this.useCanvasKit, required this.benchmarkServerPort, required this.chromeDebugPort, required this.headless, required this.treeShakeIcons, - this.useWasm = false, + this.compilationOptions = const CompilationOptions(), this.initialPage = defaultInitialPage, }); @@ -73,11 +72,8 @@ class BenchmarkServer { /// the app. final String entryPoint; - /// Whether to build the app in CanvasKit mode. - final bool useCanvasKit; - - /// Whether to build the app with dart2wasm. - final bool useWasm; + /// The compilation options to use for building the benchmark web app. + final CompilationOptions compilationOptions; /// The port this benchmark server serves the app on. final int benchmarkServerPort; @@ -118,12 +114,12 @@ class BenchmarkServer { 'flutter', 'build', 'web', - if (useWasm) ...[ + if (compilationOptions.useWasm) ...[ '--wasm', '--wasm-opt=debug', '--omit-type-checks', ], - if (useCanvasKit) '--web-renderer=canvaskit', + '--web-renderer=${compilationOptions.renderer.name}', '--dart-define=FLUTTER_WEB_ENABLE_PROFILING=true', if (!treeShakeIcons) '--no-tree-shake-icons', '--profile', @@ -343,3 +339,33 @@ class BenchmarkServer { } } } + +/// Compilation options for bulding a Flutter web app. +/// +/// This object holds metadata that is used to determine how the benchmark app +/// should be built. +class CompilationOptions { + /// Creates a [CompilationOptions] object. + const CompilationOptions({ + this.renderer = WebRenderer.html, + this.useWasm = false, + }); + + /// The renderer to use for the build. + final WebRenderer renderer; + + /// Whether to build the app with dart2wasm. + final bool useWasm; +} + +/// The possible types of web renderers Flutter can build for. +enum WebRenderer { + /// The HTML web renderer. + html, + + /// The CanvasKit web renderer. + canvaskit, + + /// The SKIA Wasm web renderer. + skwasm, +} diff --git a/packages/web_benchmarks/pubspec.yaml b/packages/web_benchmarks/pubspec.yaml index a07ea54bc06..c0222abe91c 100644 --- a/packages/web_benchmarks/pubspec.yaml +++ b/packages/web_benchmarks/pubspec.yaml @@ -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: 0.1.0+12 +version: 1.0.0 environment: sdk: ">=3.2.0 <4.0.0" diff --git a/packages/web_benchmarks/testing/web_benchmarks_test.dart b/packages/web_benchmarks/testing/web_benchmarks_test.dart index b76641a6b66..a9b0c726674 100644 --- a/packages/web_benchmarks/testing/web_benchmarks_test.dart +++ b/packages/web_benchmarks/testing/web_benchmarks_test.dart @@ -9,6 +9,7 @@ import 'package:test/test.dart'; import 'package:web_benchmarks/server.dart'; import 'package:web_benchmarks/src/common.dart'; +import 'package:web_benchmarks/src/runner.dart'; Future main() async { test('Can run a web benchmark', () async { @@ -30,7 +31,7 @@ Future main() async { await _runBenchmarks( benchmarkNames: ['simple'], entryPoint: 'lib/benchmarks/runner_simple.dart', - useWasm: true, + compilationOptions: const CompilationOptions(useWasm: true), ); }, timeout: Timeout.none); } @@ -39,15 +40,14 @@ Future _runBenchmarks({ required List benchmarkNames, required String entryPoint, String initialPage = defaultInitialPage, - bool useWasm = false, + CompilationOptions compilationOptions = const CompilationOptions(), }) async { final BenchmarkResults taskResult = await serveWebBenchmark( benchmarkAppDirectory: Directory('testing/test_app'), entryPoint: entryPoint, - useCanvasKit: false, treeShakeIcons: false, initialPage: initialPage, - useWasm: useWasm, + compilationOptions: compilationOptions, ); for (final String benchmarkName in benchmarkNames) { From d699726ec24934bebc616e7788a2f371bf563395 Mon Sep 17 00:00:00 2001 From: Kenzie Schmoll Date: Thu, 7 Dec 2023 12:26:19 -0800 Subject: [PATCH 4/6] changelog --- packages/web_benchmarks/CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/web_benchmarks/CHANGELOG.md b/packages/web_benchmarks/CHANGELOG.md index c393626e6a1..1d2f61f5c58 100644 --- a/packages/web_benchmarks/CHANGELOG.md +++ b/packages/web_benchmarks/CHANGELOG.md @@ -1,7 +1,9 @@ ## 1.0.0 -* **Breaking change:** replace 'useCanvasKit' parameter with 'compilationOptions'. -* Add the ability to run a benchmark with WebAssembly. +* **Breaking change:** replace the `useCanvasKit` parameter in the `serveWebBenchmark` +method with a new parameter `compilationOptions`, which allows you to: + * specify the web renderer to use for the benchmark app (html, canvaskit, or skwasm) + * specify whether to use WebAssembly to build the benchmark app ## 0.1.0+11 From 4551a4c6aff7a2e8eec87fcc0fc73adc1e92c3c4 Mon Sep 17 00:00:00 2001 From: Kenzie Schmoll Date: Thu, 7 Dec 2023 13:52:52 -0800 Subject: [PATCH 5/6] use canvaskit as default and expose CompilationOptions class --- packages/web_benchmarks/CHANGELOG.md | 2 ++ packages/web_benchmarks/lib/server.dart | 2 ++ .../lib/src/compilation_options.dart | 33 +++++++++++++++++++ packages/web_benchmarks/lib/src/runner.dart | 31 +---------------- .../testing/web_benchmarks_test.dart | 1 - 5 files changed, 38 insertions(+), 31 deletions(-) create mode 100644 packages/web_benchmarks/lib/src/compilation_options.dart diff --git a/packages/web_benchmarks/CHANGELOG.md b/packages/web_benchmarks/CHANGELOG.md index 1d2f61f5c58..b70677fb31b 100644 --- a/packages/web_benchmarks/CHANGELOG.md +++ b/packages/web_benchmarks/CHANGELOG.md @@ -4,6 +4,8 @@ method with a new parameter `compilationOptions`, which allows you to: * specify the web renderer to use for the benchmark app (html, canvaskit, or skwasm) * specify whether to use WebAssembly to build the benchmark app +* **Breaking change:** `serveWebBenchmark` now uses `canvaskit` instead of `html` as the +default web renderer. ## 0.1.0+11 diff --git a/packages/web_benchmarks/lib/server.dart b/packages/web_benchmarks/lib/server.dart index c4a51ca5d34..1742ac507c9 100644 --- a/packages/web_benchmarks/lib/server.dart +++ b/packages/web_benchmarks/lib/server.dart @@ -9,9 +9,11 @@ import 'package:logging/logging.dart'; import 'src/benchmark_result.dart'; import 'src/common.dart'; +import 'src/compilation_options.dart'; import 'src/runner.dart'; export 'src/benchmark_result.dart'; +export 'src/compilation_options.dart'; /// The default port number used by the local benchmark server. const int defaultBenchmarkServerPort = 9999; diff --git a/packages/web_benchmarks/lib/src/compilation_options.dart b/packages/web_benchmarks/lib/src/compilation_options.dart new file mode 100644 index 00000000000..48ec869a4ba --- /dev/null +++ b/packages/web_benchmarks/lib/src/compilation_options.dart @@ -0,0 +1,33 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// Compilation options for bulding a Flutter web app. +/// +/// This object holds metadata that is used to determine how the benchmark app +/// should be built. +class CompilationOptions { + /// Creates a [CompilationOptions] object. + const CompilationOptions({ + this.renderer = WebRenderer.canvaskit, + this.useWasm = false, + }); + + /// The renderer to use for the build. + final WebRenderer renderer; + + /// Whether to build the app with dart2wasm. + final bool useWasm; +} + +/// The possible types of web renderers Flutter can build for. +enum WebRenderer { + /// The HTML web renderer. + html, + + /// The CanvasKit web renderer. + canvaskit, + + /// The SKIA Wasm web renderer. + skwasm, +} diff --git a/packages/web_benchmarks/lib/src/runner.dart b/packages/web_benchmarks/lib/src/runner.dart index b8ed072f068..6b0517fac30 100644 --- a/packages/web_benchmarks/lib/src/runner.dart +++ b/packages/web_benchmarks/lib/src/runner.dart @@ -18,6 +18,7 @@ import 'package:shelf_static/shelf_static.dart'; import 'benchmark_result.dart'; import 'browser.dart'; import 'common.dart'; +import 'compilation_options.dart'; /// The default port number used by the local benchmark server. const int defaultBenchmarkServerPort = 9999; @@ -339,33 +340,3 @@ class BenchmarkServer { } } } - -/// Compilation options for bulding a Flutter web app. -/// -/// This object holds metadata that is used to determine how the benchmark app -/// should be built. -class CompilationOptions { - /// Creates a [CompilationOptions] object. - const CompilationOptions({ - this.renderer = WebRenderer.html, - this.useWasm = false, - }); - - /// The renderer to use for the build. - final WebRenderer renderer; - - /// Whether to build the app with dart2wasm. - final bool useWasm; -} - -/// The possible types of web renderers Flutter can build for. -enum WebRenderer { - /// The HTML web renderer. - html, - - /// The CanvasKit web renderer. - canvaskit, - - /// The SKIA Wasm web renderer. - skwasm, -} diff --git a/packages/web_benchmarks/testing/web_benchmarks_test.dart b/packages/web_benchmarks/testing/web_benchmarks_test.dart index a9b0c726674..4a3ffa35169 100644 --- a/packages/web_benchmarks/testing/web_benchmarks_test.dart +++ b/packages/web_benchmarks/testing/web_benchmarks_test.dart @@ -9,7 +9,6 @@ import 'package:test/test.dart'; import 'package:web_benchmarks/server.dart'; import 'package:web_benchmarks/src/common.dart'; -import 'package:web_benchmarks/src/runner.dart'; Future main() async { test('Can run a web benchmark', () async { From dadb73fa9ea04d7c33c46e91c5a1e144d8ec1079 Mon Sep 17 00:00:00 2001 From: Kenzie Schmoll Date: Thu, 7 Dec 2023 14:25:42 -0800 Subject: [PATCH 6/6] Add some helpful logging. --- packages/web_benchmarks/lib/client.dart | 9 ++++++--- packages/web_benchmarks/lib/src/compilation_options.dart | 5 +++++ packages/web_benchmarks/lib/src/runner.dart | 8 ++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/web_benchmarks/lib/client.dart b/packages/web_benchmarks/lib/client.dart index 6f64d048995..baaab84fe50 100644 --- a/packages/web_benchmarks/lib/client.dart +++ b/packages/web_benchmarks/lib/client.dart @@ -53,15 +53,18 @@ Future runBenchmarks( final Uri currentUri = Uri.parse(window.location.href); // Create a new URI with the current 'page' value set to [initialPage] to // ensure the benchmark app is reloaded at the proper location. - final Uri newUri = Uri( + final String newUri = Uri( scheme: currentUri.scheme, host: currentUri.host, port: currentUri.port, path: initialPage, - ); + ).toString(); // Reloading the window will trigger the next benchmark to run. - window.location.replace(newUri.toString()); + await _client.printToConsole( + 'Client preparing to reload the window to: "$newUri"', + ); + window.location.replace(newUri); } Future _runBenchmark(String? benchmarkName) async { diff --git a/packages/web_benchmarks/lib/src/compilation_options.dart b/packages/web_benchmarks/lib/src/compilation_options.dart index 48ec869a4ba..3a994703c63 100644 --- a/packages/web_benchmarks/lib/src/compilation_options.dart +++ b/packages/web_benchmarks/lib/src/compilation_options.dart @@ -18,6 +18,11 @@ class CompilationOptions { /// Whether to build the app with dart2wasm. final bool useWasm; + + @override + String toString() { + return '(renderer: ${renderer.name}, compiler: ${useWasm ? 'dart2wasm' : 'dart2js'})'; + } } /// The possible types of web renderers Flutter can build for. diff --git a/packages/web_benchmarks/lib/src/runner.dart b/packages/web_benchmarks/lib/src/runner.dart index 6b0517fac30..8eeaeb0617a 100644 --- a/packages/web_benchmarks/lib/src/runner.dart +++ b/packages/web_benchmarks/lib/src/runner.dart @@ -110,6 +110,8 @@ class BenchmarkServer { "flutter executable is not runnable. Make sure it's in the PATH."); } + final DateTime startTime = DateTime.now(); + print('Building Flutter web app $compilationOptions...'); final io.ProcessResult buildResult = await _processManager.run( [ 'flutter', @@ -130,6 +132,12 @@ class BenchmarkServer { workingDirectory: benchmarkAppDirectory.path, ); + final int buildTime = Duration( + milliseconds: DateTime.now().millisecondsSinceEpoch - + startTime.millisecondsSinceEpoch, + ).inSeconds; + print('Build took ${buildTime}s to complete.'); + if (buildResult.exitCode != 0) { io.stderr.writeln(buildResult.stdout); io.stderr.writeln(buildResult.stderr);