New benchmark to measure performance of animations after removing a BackdropFilter. (#46924)
diff --git a/dev/benchmarks/macrobenchmarks/README.md b/dev/benchmarks/macrobenchmarks/README.md
index 529a45b..d8bbe9f 100644
--- a/dev/benchmarks/macrobenchmarks/README.md
+++ b/dev/benchmarks/macrobenchmarks/README.md
@@ -37,3 +37,15 @@
Results should be in the file `build/backdrop_filter_perf.timeline_summary.json`.
More detailed logs should be in `build/backdrop_filter_perf.timeline.json`.
+
+## Post Backdrop filter benchmark
+
+To run the post-backdrop filter benchmark on a device:
+
+```
+flutter drive --profile test_driver/post_backdrop_filter_perf.dart
+```
+
+Results should be in the file `build/post_backdrop_filter_perf.timeline_summary.json`.
+
+More detailed logs should be in `build/post_backdrop_filter_perf.timeline.json`.
diff --git a/dev/benchmarks/macrobenchmarks/lib/common.dart b/dev/benchmarks/macrobenchmarks/lib/common.dart
index c8d24dc..d75ce70 100644
--- a/dev/benchmarks/macrobenchmarks/lib/common.dart
+++ b/dev/benchmarks/macrobenchmarks/lib/common.dart
@@ -5,6 +5,7 @@
const String kCullOpacityRouteName = '/cull_opacity';
const String kCubicBezierRouteName = '/cubic_bezier';
const String kBackdropFilterRouteName = '/backdrop_filter';
+const String kPostBackdropFilterRouteName = '/post_backdrop_filter';
const String kSimpleAnimationRouteName = '/simple_animation';
const String kPictureCacheRouteName = '/picture_cache';
const String kLargeImagesRouteName = '/large_images';
diff --git a/dev/benchmarks/macrobenchmarks/lib/main.dart b/dev/benchmarks/macrobenchmarks/lib/main.dart
index 5a2160c..d7877bd 100644
--- a/dev/benchmarks/macrobenchmarks/lib/main.dart
+++ b/dev/benchmarks/macrobenchmarks/lib/main.dart
@@ -10,6 +10,7 @@
import 'src/backdrop_filter.dart';
import 'src/cubic_bezier.dart';
import 'src/cull_opacity.dart';
+import 'src/post_backdrop_filter.dart';
import 'src/simple_animation.dart';
const String kMacrobenchmarks ='Macrobenchmarks';
@@ -29,6 +30,7 @@
kCullOpacityRouteName: (BuildContext context) => CullOpacityPage(),
kCubicBezierRouteName: (BuildContext context) => CubicBezierPage(),
kBackdropFilterRouteName: (BuildContext context) => BackdropFilterPage(),
+ kPostBackdropFilterRouteName: (BuildContext context) => PostBackdropFilterPage(),
kSimpleAnimationRouteName: (BuildContext conttext) => SimpleAnimationPage(),
kPictureCacheRouteName: (BuildContext context) => PictureCachePage(),
kLargeImagesRouteName: (BuildContext context) => LargeImagesPage(),
@@ -68,6 +70,13 @@
},
),
RaisedButton(
+ key: const Key(kPostBackdropFilterRouteName),
+ child: const Text('Post Backdrop Filter'),
+ onPressed: () {
+ Navigator.pushNamed(context, kPostBackdropFilterRouteName);
+ },
+ ),
+ RaisedButton(
key: const Key(kSimpleAnimationRouteName),
child: const Text('Simple Animation'),
onPressed: () {
diff --git a/dev/benchmarks/macrobenchmarks/lib/src/post_backdrop_filter.dart b/dev/benchmarks/macrobenchmarks/lib/src/post_backdrop_filter.dart
new file mode 100644
index 0000000..4f348e6
--- /dev/null
+++ b/dev/benchmarks/macrobenchmarks/lib/src/post_backdrop_filter.dart
@@ -0,0 +1,101 @@
+// Copyright 2014 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.
+
+import 'dart:ui';
+
+import 'package:flutter/material.dart';
+
+class PostBackdropFilterPage extends StatefulWidget {
+ @override
+ _PostBackdropFilterPageState createState() => _PostBackdropFilterPageState();
+}
+
+class _PostBackdropFilterPageState extends State<PostBackdropFilterPage> with TickerProviderStateMixin {
+ bool _includeBackdropFilter = false;
+ AnimationController animation;
+
+ @override
+ void initState() {
+ super.initState();
+ animation = AnimationController(vsync: this, duration: const Duration(seconds: 1));
+ }
+
+ @override
+ void dispose() {
+ animation.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ Widget getConditionalBackdrop() {
+ if (_includeBackdropFilter) {
+ return Column(
+ children: <Widget>[
+ const SizedBox(height: 20),
+ ClipRect(
+ child: BackdropFilter(
+ filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
+ child: const Text('BackdropFilter'),
+ ),
+ ),
+ const SizedBox(height: 20),
+ ],
+ );
+ } else {
+ return const SizedBox(height: 20);
+ }
+ }
+
+ return Scaffold(
+ backgroundColor: Colors.grey,
+ body: Stack(
+ children: <Widget>[
+ Text('0' * 10000, style: TextStyle(color: Colors.yellow)),
+ Column(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: <Widget>[
+ Expanded(
+ child: RepaintBoundary(
+ child: Center(
+ child: AnimatedBuilder(
+ animation: animation,
+ builder: (BuildContext c, Widget w) {
+ final int val = (animation.value * 255).round();
+ return Container(
+ width: 50,
+ height: 50,
+ color: Color.fromARGB(255, val, val, val));
+ }),
+ )),
+ ),
+ getConditionalBackdrop(),
+ RepaintBoundary(
+ child: Container(
+ color: Colors.white,
+ child:Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: <Widget>[
+ const Text('Include BackdropFilter:'),
+ Checkbox(
+ key: const Key('bdf-checkbox'), // this key is used by the driver test
+ value: _includeBackdropFilter,
+ onChanged: (bool v) => setState(() { _includeBackdropFilter = v; }),
+ ),
+ MaterialButton(
+ key: const Key('bdf-animate'), // this key is used by the driver test
+ child: const Text('Animate'),
+ onPressed: () => setState(() { animation.repeat(); }),
+ ),
+ ],
+ ),
+ ),
+ )
+ ],
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/dev/benchmarks/macrobenchmarks/test_driver/post_backdrop_filter_perf.dart b/dev/benchmarks/macrobenchmarks/test_driver/post_backdrop_filter_perf.dart
new file mode 100644
index 0000000..8169d13
--- /dev/null
+++ b/dev/benchmarks/macrobenchmarks/test_driver/post_backdrop_filter_perf.dart
@@ -0,0 +1,11 @@
+// Copyright 2014 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.
+
+import 'package:flutter_driver/driver_extension.dart';
+import 'package:macrobenchmarks/main.dart' as app;
+
+void main() {
+ enableFlutterDriverExtension();
+ app.main();
+}
diff --git a/dev/benchmarks/macrobenchmarks/test_driver/post_backdrop_filter_perf_test.dart b/dev/benchmarks/macrobenchmarks/test_driver/post_backdrop_filter_perf_test.dart
new file mode 100644
index 0000000..78c6807
--- /dev/null
+++ b/dev/benchmarks/macrobenchmarks/test_driver/post_backdrop_filter_perf_test.dart
@@ -0,0 +1,28 @@
+// Copyright 2014 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.
+
+import 'package:flutter_driver/flutter_driver.dart';
+import 'package:macrobenchmarks/common.dart';
+
+import 'util.dart';
+
+void main() {
+ macroPerfTest(
+ 'post_backdrop_filter_perf',
+ kPostBackdropFilterRouteName,
+ pageDelay: const Duration(seconds: 1),
+ duration: const Duration(seconds: 10),
+ setupOps: (FlutterDriver driver) async {
+ final SerializableFinder backdropFilterCheckbox = find.byValueKey('bdf-checkbox');
+ await driver.tap(backdropFilterCheckbox);
+ await Future<void>.delayed(const Duration(milliseconds: 500)); // BackdropFilter on
+ await driver.tap(backdropFilterCheckbox);
+ await Future<void>.delayed(const Duration(milliseconds: 500)); // BackdropFilter off
+
+ final SerializableFinder animateButton = find.byValueKey('bdf-animate');
+ await driver.tap(animateButton);
+ await Future<void>.delayed(const Duration(milliseconds: 1000)); // Now animate
+ },
+ );
+}
diff --git a/dev/benchmarks/macrobenchmarks/test_driver/util.dart b/dev/benchmarks/macrobenchmarks/test_driver/util.dart
index 4597c16..22fb2fd 100644
--- a/dev/benchmarks/macrobenchmarks/test_driver/util.dart
+++ b/dev/benchmarks/macrobenchmarks/test_driver/util.dart
@@ -13,6 +13,7 @@
{ Duration pageDelay,
Duration duration = const Duration(seconds: 3),
Future<void> driverOps(FlutterDriver driver),
+ Future<void> setupOps(FlutterDriver driver),
}) {
test(testName, () async {
final FlutterDriver driver = await FlutterDriver.connect();
@@ -34,6 +35,10 @@
await Future<void>.delayed(pageDelay);
}
+ if (setupOps != null) {
+ await setupOps(driver);
+ }
+
final Timeline timeline = await driver.traceAction(() async {
final Future<void> durationFuture = Future<void>.delayed(duration);
if (driverOps != null) {
diff --git a/dev/devicelab/bin/tasks/post_backdrop_filter_perf_ios__timeline_summary.dart b/dev/devicelab/bin/tasks/post_backdrop_filter_perf_ios__timeline_summary.dart
new file mode 100644
index 0000000..dc3b0b3
--- /dev/null
+++ b/dev/devicelab/bin/tasks/post_backdrop_filter_perf_ios__timeline_summary.dart
@@ -0,0 +1,14 @@
+// Copyright 2014 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.
+
+import 'dart:async';
+
+import 'package:flutter_devicelab/tasks/perf_tests.dart';
+import 'package:flutter_devicelab/framework/adb.dart';
+import 'package:flutter_devicelab/framework/framework.dart';
+
+Future<void> main() async {
+ deviceOperatingSystem = DeviceOperatingSystem.ios;
+ await task(createPostBackdropFilterPerfTest(needsMeasureCpuGpu: true));
+}
diff --git a/dev/devicelab/lib/tasks/perf_tests.dart b/dev/devicelab/lib/tasks/perf_tests.dart
index 0a1d858..fc3c57a 100644
--- a/dev/devicelab/lib/tasks/perf_tests.dart
+++ b/dev/devicelab/lib/tasks/perf_tests.dart
@@ -63,6 +63,15 @@
).run;
}
+TaskFunction createPostBackdropFilterPerfTest({bool needsMeasureCpuGpu = false}) {
+ return PerfTest(
+ '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
+ 'test_driver/post_backdrop_filter_perf.dart',
+ 'post_backdrop_filter_perf',
+ needsMeasureCpuGPu: needsMeasureCpuGpu,
+ ).run;
+}
+
TaskFunction createSimpleAnimationPerfTest({bool needsMeasureCpuGpu = false}) {
return PerfTest(
'${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
diff --git a/dev/devicelab/manifest.yaml b/dev/devicelab/manifest.yaml
index a0a389a..e02bea0 100644
--- a/dev/devicelab/manifest.yaml
+++ b/dev/devicelab/manifest.yaml
@@ -463,6 +463,12 @@
stage: devicelab_ios
required_agent_capabilities: ["mac/ios"]
+ post_backdrop_filter_perf_ios__timeline_summary:
+ description: >
+ Measures the runtime performance of animations after a backdrop filter is removed on iOS.
+ stage: devicelab_ios
+ required_agent_capabilities: ["mac/ios"]
+
complex_layout_scroll_perf_ios__timeline_summary:
description: >
Measures the runtime performance of the Complex Layout sample app on