add benchmarks to track web size (#33892)


diff --git a/dev/devicelab/bin/tasks/web_size__compile_test.dart b/dev/devicelab/bin/tasks/web_size__compile_test.dart
new file mode 100644
index 0000000..f54bce5
--- /dev/null
+++ b/dev/devicelab/bin/tasks/web_size__compile_test.dart
@@ -0,0 +1,10 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter_devicelab/framework/framework.dart';
+import 'package:flutter_devicelab/tasks/perf_tests.dart';
+
+Future<void> main() async {
+   await task(createWebCompileTest());
+}
diff --git a/dev/devicelab/lib/tasks/perf_tests.dart b/dev/devicelab/lib/tasks/perf_tests.dart
index c82e016..13461de 100644
--- a/dev/devicelab/lib/tasks/perf_tests.dart
+++ b/dev/devicelab/lib/tasks/perf_tests.dart
@@ -74,6 +74,10 @@
   return CompileTest('${flutterDirectory.path}/examples/hello_world', reportPackageContentSizes: true).run;
 }
 
+TaskFunction createWebCompileTest() {
+  return const WebCompileTest().run;
+}
+
 TaskFunction createComplexLayoutCompileTest() {
   return CompileTest('${flutterDirectory.path}/dev/benchmarks/complex_layout').run;
 }
@@ -198,6 +202,71 @@
   }
 }
 
+/// Measures how long it takes to compile a Flutter app to JavaScript and how
+/// big the compiled code is.
+class WebCompileTest {
+  const WebCompileTest();
+
+  Future<TaskResult> run() async {
+    final Map<String, Object> metrics = <String, Object>{};
+    await inDirectory<TaskResult>('${flutterDirectory.path}/examples/hello_world', () async {
+      await flutter('packages', options: <String>['get']);
+      await evalFlutter('build', options: <String>[
+        'web',
+        '-v',
+        '--release',
+        '--no-pub',
+      ]);
+      final String output = '${flutterDirectory.path}/examples/hello_world/build/web/main.dart.js';
+      await _measureSize('hello_world', output, metrics);
+      return null;
+    });
+    await inDirectory<TaskResult>('${flutterDirectory.path}/examples/flutter_gallery', () async {
+      await flutter('packages', options: <String>['get']);
+      await evalFlutter('build', options: <String>[
+        'web',
+        '-v',
+        '--release',
+        '--no-pub',
+      ]);
+      final String output = '${flutterDirectory.path}/examples/flutter_gallery/build/web/main.dart.js';
+      await _measureSize('flutter_gallery', output, metrics);
+      return null;
+    });
+    const String sampleAppName = 'sample_flutter_app';
+    final Directory sampleDir = dir('${Directory.systemTemp.path}/$sampleAppName');
+
+    rmTree(sampleDir);
+
+    await inDirectory<void>(Directory.systemTemp, () async {
+      await flutter('create', options: <String>['--template=app', sampleAppName]);
+      await inDirectory(sampleDir, () async {
+        await flutter('packages', options: <String>['get']);
+        await evalFlutter('build', options: <String>[
+          'web',
+          '-v',
+          '--release',
+          '--no-pub',
+        ]);
+        await _measureSize('basic_material_app', path.join(sampleDir.path, 'build/web/main.dart.js'), metrics);
+      });
+    });
+    return TaskResult.success(metrics, benchmarkScoreKeys: metrics.keys.toList());
+  }
+
+  static Future<void> _measureSize(String metric, String output, Map<String, Object> metrics) async {
+    final ProcessResult result = await Process.run('du', <String>['-k', output]);
+    await Process.run('gzip',<String>['-k', '9', output]);
+    final ProcessResult resultGzip = await Process.run('du', <String>['-k', output + '.gz']);
+    metrics['${metric}_dart2js_size'] = _parseDu(result.stdout);
+    metrics['${metric}_dart2js_size_gzip'] = _parseDu(resultGzip.stdout);
+  }
+
+  static int _parseDu(String source) {
+    return int.parse(source.split(RegExp(r'\s+')).first.trim());
+  }
+}
+
 /// Measures how long it takes to compile a Flutter app and how big the compiled
 /// code is.
 class CompileTest {
diff --git a/dev/devicelab/manifest.yaml b/dev/devicelab/manifest.yaml
index 02b57ce..4a7a646 100644
--- a/dev/devicelab/manifest.yaml
+++ b/dev/devicelab/manifest.yaml
@@ -338,6 +338,14 @@
     required_agent_capabilities: ["linux/android"]
     flaky: true
 
+  web_size__compile_test:
+    description: >
+      Measures the size of a dart2js bundle.
+    stage: devicelab
+    required_agent_capabilities: ["linux/android"]
+    flaky: true
+
+
   # iOS on-device tests
 
   flavors_test_ios:
diff --git a/packages/flutter_tools/lib/src/web/compile.dart b/packages/flutter_tools/lib/src/web/compile.dart
index b814d40..e987498 100644
--- a/packages/flutter_tools/lib/src/web/compile.dart
+++ b/packages/flutter_tools/lib/src/web/compile.dart
@@ -58,6 +58,7 @@
       target,
       '-o',
       '$outputPath',
+      '-O4',
       '--libraries-spec=$librariesPath',
     ];
     if (minify) {
diff --git a/packages/flutter_tools/test/web/compile_test.dart b/packages/flutter_tools/test/web/compile_test.dart
index edcb080..425c79d 100644
--- a/packages/flutter_tools/test/web/compile_test.dart
+++ b/packages/flutter_tools/test/web/compile_test.dart
@@ -38,6 +38,7 @@
         'lib/main.dart',
         '-o',
         'build/web/main.dart.js',
+        '-O4',
         '--libraries-spec=bin/cache/flutter_web_sdk/libraries.json',
         '-m',
       ])).called(1);