From 360023e2bcb17fa63a563aebe8dc6ef6428c84cd Mon Sep 17 00:00:00 2001 From: "Ming Lyu (CareF)" Date: Thu, 13 Aug 2020 17:41:04 -0400 Subject: [PATCH] Clean up flutter_gallery__transition_perf (#63609) --- ...utter_gallery__transition_perf_hybrid.dart | 14 ++++ dev/devicelab/lib/tasks/gallery.dart | 30 ++++--- dev/devicelab/manifest.yaml | 10 +++ .../test_driver/run_demos.dart | 80 +++++++++++++++++++ .../test_driver/transitions_perf.dart | 41 ++++++++-- .../test_driver/transitions_perf_e2e.dart | 70 +--------------- .../transitions_perf_hybrid_test.dart | 9 +++ .../test_driver/transitions_perf_test.dart | 15 +++- .../transitions_perf_with_semantics.dart | 9 --- 9 files changed, 181 insertions(+), 97 deletions(-) create mode 100644 dev/devicelab/bin/tasks/flutter_gallery__transition_perf_hybrid.dart create mode 100644 dev/integration_tests/flutter_gallery/test_driver/run_demos.dart create mode 100644 dev/integration_tests/flutter_gallery/test_driver/transitions_perf_hybrid_test.dart delete mode 100644 dev/integration_tests/flutter_gallery/test_driver/transitions_perf_with_semantics.dart diff --git a/dev/devicelab/bin/tasks/flutter_gallery__transition_perf_hybrid.dart b/dev/devicelab/bin/tasks/flutter_gallery__transition_perf_hybrid.dart new file mode 100644 index 00000000000..89430ced232 --- /dev/null +++ b/dev/devicelab/bin/tasks/flutter_gallery__transition_perf_hybrid.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/gallery.dart'; +import 'package:flutter_devicelab/framework/adb.dart'; +import 'package:flutter_devicelab/framework/framework.dart'; + +Future main() async { + deviceOperatingSystem = DeviceOperatingSystem.android; + await task(createGalleryTransitionHybridTest()); +} diff --git a/dev/devicelab/lib/tasks/gallery.dart b/dev/devicelab/lib/tasks/gallery.dart index f525fa03876..9481cdb7daa 100644 --- a/dev/devicelab/lib/tasks/gallery.dart +++ b/dev/devicelab/lib/tasks/gallery.dart @@ -11,14 +11,15 @@ import '../framework/adb.dart'; import '../framework/framework.dart'; import '../framework/utils.dart'; -TaskFunction createGalleryTransitionTest({ bool semanticsEnabled = false }) { +TaskFunction createGalleryTransitionTest({bool semanticsEnabled = false}) { return GalleryTransitionTest(semanticsEnabled: semanticsEnabled); } -TaskFunction createGalleryTransitionE2ETest({ bool semanticsEnabled = false }) { +TaskFunction createGalleryTransitionE2ETest({bool semanticsEnabled = false}) { return GalleryTransitionTest( - semanticsEnabled: semanticsEnabled, - testFile: 'transitions_perf_e2e', + testFile: semanticsEnabled + ? 'transitions_perf_e2e_with_semantics' + : 'transitions_perf_e2e', needFullTimeline: false, timelineSummaryFile: 'e2e_perf_summary', transitionDurationFile: null, @@ -26,6 +27,15 @@ TaskFunction createGalleryTransitionE2ETest({ bool semanticsEnabled = false }) { ); } +TaskFunction createGalleryTransitionHybridTest({bool semanticsEnabled = false}) { + return GalleryTransitionTest( + semanticsEnabled: semanticsEnabled, + driverFile: semanticsEnabled + ? 'transitions_perf_hybrid_with_semantics_test' + : 'transitions_perf_hybrid_test', + ); +} + class GalleryTransitionTest { GalleryTransitionTest({ @@ -53,18 +63,18 @@ class GalleryTransitionTest { await inDirectory(galleryDirectory, () async { await flutter('packages', options: ['get']); - final String testDriver = semanticsEnabled - ? '${testFile}_with_semantics.dart' - : '$testFile.dart'; + final String testDriver = driverFile ?? (semanticsEnabled + ? '${testFile}_test' + : '${testFile}_with_semantics_test'); await flutter('drive', options: [ '--profile', if (needFullTimeline) '--trace-startup', '-t', - 'test_driver/$testDriver', - if (driverFile != null) - ...['--driver', 'test_driver/$driverFile.dart'], + 'test_driver/$testFile.dart', + '--driver', + 'test_driver/$testDriver.dart', '-d', deviceId, ]); diff --git a/dev/devicelab/manifest.yaml b/dev/devicelab/manifest.yaml index 9f60c8c3478..44b8dbc73dc 100644 --- a/dev/devicelab/manifest.yaml +++ b/dev/devicelab/manifest.yaml @@ -769,6 +769,16 @@ tasks: required_agent_capabilities: ["linux/android"] flaky: true + flutter_gallery__transition_perf_hybrid: + description: > + Measures the performance of screen transitions in Flutter Gallery on + Android where the page transitions are self-driven on device without host + interventions, but the timeline events are still sent to host to be + processed. + stage: devicelab + required_agent_capabilities: ["linux/android"] + flaky: true + flutter_gallery_sksl_warmup__transition_perf: description: > Measures the runtime performance of Flutter gallery transitions on Android diff --git a/dev/integration_tests/flutter_gallery/test_driver/run_demos.dart b/dev/integration_tests/flutter_gallery/test_driver/run_demos.dart new file mode 100644 index 00000000000..6a67963edfe --- /dev/null +++ b/dev/integration_tests/flutter_gallery/test_driver/run_demos.dart @@ -0,0 +1,80 @@ +// 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 'dart:ui'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:flutter_gallery/demo_lists.dart'; + +const List kSkippedDemos = []; + +/// Scrolls each demo menu item into view, launches it, then returns to the +/// home screen twice. +Future runDemos(List demos, WidgetController controller) async { + final Finder demoList = find.byType(Scrollable); + String currentDemoCategory; + + for (final String demo in demos) { + if (kSkippedDemos.contains(demo)) + continue; + + final String demoName = demo.substring(0, demo.indexOf('@')); + final String demoCategory = demo.substring(demo.indexOf('@') + 1); + print('> $demo'); + await controller.pump(const Duration(milliseconds: 250)); + + if (currentDemoCategory == null) { + await controller.tap(find.text(demoCategory)); + await controller.pumpAndSettle(); + } else if (currentDemoCategory != demoCategory) { + await controller.tap(find.byTooltip('Back')); + await controller.pumpAndSettle(); + await controller.tap(find.text(demoCategory)); + await controller.pumpAndSettle(); + // Scroll back to the top + await controller.drag(demoList, const Offset(0.0, 10000.0)); + await controller.pumpAndSettle(const Duration(milliseconds: 100)); + } + currentDemoCategory = demoCategory; + + final Finder demoItem = find.text(demoName); + await controller.scrollUntilVisible(demoItem, 48.0); + await controller.pumpAndSettle(); + + Future pageBack() { + Finder backButton = find.byTooltip('Back'); + if (backButton.evaluate().isEmpty) { + backButton = find.byType(CupertinoNavigationBarBackButton); + } + return controller.tap(backButton); + } + + for (int i = 0; i < 2; i += 1) { + await controller.tap(demoItem); // Launch the demo + + if (kUnsynchronizedDemos.contains(demo)) { + // These tests have animation, pumpAndSettle cannot be used. + // This time is questionable. 400ms is the tested reasonable result. + await controller.pump(const Duration(milliseconds: 400)); + await controller.pump(); + await pageBack(); + } else { + await controller.pumpAndSettle(); + // page back + await pageBack(); + } + await controller.pumpAndSettle(); + } + + print('< Success'); + } + + // Return to the home screen + await controller.tap(find.byTooltip('Back')); + await controller.pumpAndSettle(); +} diff --git a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf.dart b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf.dart index 53b07e97ab9..5c34a1f340e 100644 --- a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf.dart +++ b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf.dart @@ -7,18 +7,47 @@ import 'dart:convert' show JsonEncoder; import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_gallery/gallery/demos.dart'; +import 'package:flutter_gallery/demo_lists.dart'; import 'package:flutter_gallery/gallery/app.dart' show GalleryApp; +import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/material.dart'; -Future _handleMessages(String message) async { - assert(message == 'demoNames'); - return const JsonEncoder.withIndent(' ').convert( - kAllGalleryDemos.map((GalleryDemo demo) => '${demo.title}@${demo.category.name}').toList(), - ); +import 'run_demos.dart'; + +// All of the gallery demos, identified as "title@category". +// +// These names are reported by the test app, see _handleMessages() +// in transitions_perf.dart. +List _allDemos = kAllGalleryDemos.map( + (GalleryDemo demo) => '${demo.title}@${demo.category.name}', +).toList(); + +Set _unTestedDemos = Set.from(_allDemos); + +class _MessageHandler { + static LiveWidgetController controller; + Future call(String message) async { + switch(message) { + case 'demoNames': + return const JsonEncoder.withIndent(' ').convert(_allDemos); + case 'profileDemos': + controller ??= LiveWidgetController(WidgetsBinding.instance); + await runDemos(kProfiledDemos, controller); + _unTestedDemos.removeAll(kProfiledDemos); + return const JsonEncoder.withIndent(' ').convert(kProfiledDemos); + case 'restDemos': + controller ??= LiveWidgetController(WidgetsBinding.instance); + final List restDemos = _unTestedDemos.toList(); + await runDemos(restDemos, controller); + return const JsonEncoder.withIndent(' ').convert(restDemos); + default: + throw ArgumentError; + } + } } void main() { - enableFlutterDriverExtension(handler: _handleMessages); + enableFlutterDriverExtension(handler: _MessageHandler()); // As in lib/main.dart: overriding https://github.com/flutter/flutter/issues/13736 // for better visual effect at the cost of performance. runApp(const GalleryApp(testMode: true)); diff --git a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_e2e.dart b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_e2e.dart index a38810df75e..3ebe0e4f482 100644 --- a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_e2e.dart +++ b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_e2e.dart @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; -import 'dart:ui'; - import 'package:flutter/cupertino.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -16,6 +13,7 @@ import 'package:flutter_gallery/gallery/demos.dart'; import 'package:flutter_gallery/demo_lists.dart'; import 'e2e_utils.dart'; +import 'run_demos.dart'; const List kSkippedDemos = []; @@ -27,72 +25,6 @@ List _allDemos = kAllGalleryDemos.map( (GalleryDemo demo) => '${demo.title}@${demo.category.name}', ).toList(); -/// Scrolls each demo menu item into view, launches it, then returns to the -/// home screen twice. -Future runDemos(List demos, WidgetController controller) async { - final Finder demoList = find.byType(Scrollable); - String currentDemoCategory; - - for (final String demo in demos) { - if (kSkippedDemos.contains(demo)) - continue; - - final String demoName = demo.substring(0, demo.indexOf('@')); - final String demoCategory = demo.substring(demo.indexOf('@') + 1); - print('> $demo'); - await controller.pump(const Duration(milliseconds: 250)); - - if (currentDemoCategory == null) { - await controller.tap(find.text(demoCategory)); - await controller.pumpAndSettle(); - } else if (currentDemoCategory != demoCategory) { - await controller.tap(find.byTooltip('Back')); - await controller.pumpAndSettle(); - await controller.tap(find.text(demoCategory)); - await controller.pumpAndSettle(); - // Scroll back to the top - await controller.drag(demoList, const Offset(0.0, 10000.0)); - await controller.pumpAndSettle(const Duration(milliseconds: 100)); - } - currentDemoCategory = demoCategory; - - final Finder demoItem = find.text(demoName); - await controller.scrollUntilVisible(demoItem, 48.0); - await controller.pumpAndSettle(); - - Future pageBack() { - Finder backButton = find.byTooltip('Back'); - if (backButton.evaluate().isEmpty) { - backButton = find.byType(CupertinoNavigationBarBackButton); - } - return controller.tap(backButton); - } - - for (int i = 0; i < 2; i += 1) { - await controller.tap(demoItem); // Launch the demo - - if (kUnsynchronizedDemos.contains(demo)) { - // These tests have animation, pumpAndSettle cannot be used. - // This time is questionable. 300ms is the tested reasonable result. - await controller.pump(const Duration(milliseconds: 300)); - await controller.pump(); - await pageBack(); - } else { - await controller.pumpAndSettle(); - // page back - await pageBack(); - } - await controller.pumpAndSettle(); - } - - print('< Success'); - } - - // Return to the home screen - await controller.tap(find.byTooltip('Back')); - await controller.pumpAndSettle(); -} - void main([List args = const []]) { final bool withSemantics = args.contains('--with_semantics'); final E2EWidgetsFlutterBinding binding = diff --git a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_hybrid_test.dart b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_hybrid_test.dart new file mode 100644 index 00000000000..dc5ab42f021 --- /dev/null +++ b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_hybrid_test.dart @@ -0,0 +1,9 @@ +// 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 'transitions_perf_test.dart' as transitions_perf_test; + +void main([List args = const []]) => transitions_perf_test.main( + ['--hybrid', ...args], +); diff --git a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_test.dart b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_test.dart index b209aac2164..7ed0aa8b8f1 100644 --- a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_test.dart +++ b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_test.dart @@ -153,6 +153,7 @@ Future runDemos(List demos, FlutterDriver driver) async { void main([List args = const []]) { final bool withSemantics = args.contains('--with_semantics'); + final bool hybrid = args.contains('--hybrid'); group('flutter gallery transitions', () { FlutterDriver driver; setUpAll(() async { @@ -186,7 +187,11 @@ void main([List args = const []]) { // Collect timeline data for just a limited set of demos to avoid OOMs. final Timeline timeline = await driver.traceAction( () async { - await runDemos(kProfiledDemos, driver); + if (hybrid) { + await driver.requestData('profileDemos'); + } else { + await runDemos(kProfiledDemos, driver); + } }, streams: const [ TimelineStream.dart, @@ -205,8 +210,12 @@ void main([List args = const []]) { histogramPath); // Execute the remaining tests. - final Set unprofiledDemos = Set.from(_allDemos)..removeAll(kProfiledDemos); - await runDemos(unprofiledDemos.toList(), driver); + if (hybrid) { + await driver.requestData('profileDemos'); + } else { + final Set unprofiledDemos = Set.from(_allDemos)..removeAll(kProfiledDemos); + await runDemos(unprofiledDemos.toList(), driver); + } }, timeout: const Timeout(Duration(minutes: 5))); }); diff --git a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_with_semantics.dart b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_with_semantics.dart deleted file mode 100644 index 4435996f9db..00000000000 --- a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_with_semantics.dart +++ /dev/null @@ -1,9 +0,0 @@ -// 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 'transitions_perf.dart' as transitions_perf; - -void main() { - transitions_perf.main(); -}