mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Clean up flutter_gallery__transition_perf (#63609)
This commit is contained in:
parent
8f896c9027
commit
360023e2bc
@ -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<void> main() async {
|
||||||
|
deviceOperatingSystem = DeviceOperatingSystem.android;
|
||||||
|
await task(createGalleryTransitionHybridTest());
|
||||||
|
}
|
@ -11,14 +11,15 @@ import '../framework/adb.dart';
|
|||||||
import '../framework/framework.dart';
|
import '../framework/framework.dart';
|
||||||
import '../framework/utils.dart';
|
import '../framework/utils.dart';
|
||||||
|
|
||||||
TaskFunction createGalleryTransitionTest({ bool semanticsEnabled = false }) {
|
TaskFunction createGalleryTransitionTest({bool semanticsEnabled = false}) {
|
||||||
return GalleryTransitionTest(semanticsEnabled: semanticsEnabled);
|
return GalleryTransitionTest(semanticsEnabled: semanticsEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskFunction createGalleryTransitionE2ETest({ bool semanticsEnabled = false }) {
|
TaskFunction createGalleryTransitionE2ETest({bool semanticsEnabled = false}) {
|
||||||
return GalleryTransitionTest(
|
return GalleryTransitionTest(
|
||||||
semanticsEnabled: semanticsEnabled,
|
testFile: semanticsEnabled
|
||||||
testFile: 'transitions_perf_e2e',
|
? 'transitions_perf_e2e_with_semantics'
|
||||||
|
: 'transitions_perf_e2e',
|
||||||
needFullTimeline: false,
|
needFullTimeline: false,
|
||||||
timelineSummaryFile: 'e2e_perf_summary',
|
timelineSummaryFile: 'e2e_perf_summary',
|
||||||
transitionDurationFile: null,
|
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 {
|
class GalleryTransitionTest {
|
||||||
|
|
||||||
GalleryTransitionTest({
|
GalleryTransitionTest({
|
||||||
@ -53,18 +63,18 @@ class GalleryTransitionTest {
|
|||||||
await inDirectory<void>(galleryDirectory, () async {
|
await inDirectory<void>(galleryDirectory, () async {
|
||||||
await flutter('packages', options: <String>['get']);
|
await flutter('packages', options: <String>['get']);
|
||||||
|
|
||||||
final String testDriver = semanticsEnabled
|
final String testDriver = driverFile ?? (semanticsEnabled
|
||||||
? '${testFile}_with_semantics.dart'
|
? '${testFile}_test'
|
||||||
: '$testFile.dart';
|
: '${testFile}_with_semantics_test');
|
||||||
|
|
||||||
await flutter('drive', options: <String>[
|
await flutter('drive', options: <String>[
|
||||||
'--profile',
|
'--profile',
|
||||||
if (needFullTimeline)
|
if (needFullTimeline)
|
||||||
'--trace-startup',
|
'--trace-startup',
|
||||||
'-t',
|
'-t',
|
||||||
'test_driver/$testDriver',
|
'test_driver/$testFile.dart',
|
||||||
if (driverFile != null)
|
'--driver',
|
||||||
...<String>['--driver', 'test_driver/$driverFile.dart'],
|
'test_driver/$testDriver.dart',
|
||||||
'-d',
|
'-d',
|
||||||
deviceId,
|
deviceId,
|
||||||
]);
|
]);
|
||||||
|
@ -769,6 +769,16 @@ tasks:
|
|||||||
required_agent_capabilities: ["linux/android"]
|
required_agent_capabilities: ["linux/android"]
|
||||||
flaky: true
|
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:
|
flutter_gallery_sksl_warmup__transition_perf:
|
||||||
description: >
|
description: >
|
||||||
Measures the runtime performance of Flutter gallery transitions on Android
|
Measures the runtime performance of Flutter gallery transitions on Android
|
||||||
|
@ -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<String> kSkippedDemos = <String>[];
|
||||||
|
|
||||||
|
/// Scrolls each demo menu item into view, launches it, then returns to the
|
||||||
|
/// home screen twice.
|
||||||
|
Future<void> runDemos(List<String> 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<void> 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();
|
||||||
|
}
|
@ -7,18 +7,47 @@ import 'dart:convert' show JsonEncoder;
|
|||||||
|
|
||||||
import 'package:flutter_driver/driver_extension.dart';
|
import 'package:flutter_driver/driver_extension.dart';
|
||||||
import 'package:flutter_gallery/gallery/demos.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_gallery/gallery/app.dart' show GalleryApp;
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
Future<String> _handleMessages(String message) async {
|
import 'run_demos.dart';
|
||||||
assert(message == 'demoNames');
|
|
||||||
return const JsonEncoder.withIndent(' ').convert(
|
// All of the gallery demos, identified as "title@category".
|
||||||
kAllGalleryDemos.map((GalleryDemo demo) => '${demo.title}@${demo.category.name}').toList(),
|
//
|
||||||
);
|
// These names are reported by the test app, see _handleMessages()
|
||||||
|
// in transitions_perf.dart.
|
||||||
|
List<String> _allDemos = kAllGalleryDemos.map(
|
||||||
|
(GalleryDemo demo) => '${demo.title}@${demo.category.name}',
|
||||||
|
).toList();
|
||||||
|
|
||||||
|
Set<String> _unTestedDemos = Set<String>.from(_allDemos);
|
||||||
|
|
||||||
|
class _MessageHandler {
|
||||||
|
static LiveWidgetController controller;
|
||||||
|
Future<String> 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<String> restDemos = _unTestedDemos.toList();
|
||||||
|
await runDemos(restDemos, controller);
|
||||||
|
return const JsonEncoder.withIndent(' ').convert(restDemos);
|
||||||
|
default:
|
||||||
|
throw ArgumentError;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
enableFlutterDriverExtension(handler: _handleMessages);
|
enableFlutterDriverExtension(handler: _MessageHandler());
|
||||||
// As in lib/main.dart: overriding https://github.com/flutter/flutter/issues/13736
|
// As in lib/main.dart: overriding https://github.com/flutter/flutter/issues/13736
|
||||||
// for better visual effect at the cost of performance.
|
// for better visual effect at the cost of performance.
|
||||||
runApp(const GalleryApp(testMode: true));
|
runApp(const GalleryApp(testMode: true));
|
||||||
|
@ -2,9 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:async';
|
|
||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_test/flutter_test.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 'package:flutter_gallery/demo_lists.dart';
|
||||||
|
|
||||||
import 'e2e_utils.dart';
|
import 'e2e_utils.dart';
|
||||||
|
import 'run_demos.dart';
|
||||||
|
|
||||||
const List<String> kSkippedDemos = <String>[];
|
const List<String> kSkippedDemos = <String>[];
|
||||||
|
|
||||||
@ -27,72 +25,6 @@ List<String> _allDemos = kAllGalleryDemos.map(
|
|||||||
(GalleryDemo demo) => '${demo.title}@${demo.category.name}',
|
(GalleryDemo demo) => '${demo.title}@${demo.category.name}',
|
||||||
).toList();
|
).toList();
|
||||||
|
|
||||||
/// Scrolls each demo menu item into view, launches it, then returns to the
|
|
||||||
/// home screen twice.
|
|
||||||
Future<void> runDemos(List<String> 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<void> 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<String> args = const <String>[]]) {
|
void main([List<String> args = const <String>[]]) {
|
||||||
final bool withSemantics = args.contains('--with_semantics');
|
final bool withSemantics = args.contains('--with_semantics');
|
||||||
final E2EWidgetsFlutterBinding binding =
|
final E2EWidgetsFlutterBinding binding =
|
||||||
|
@ -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<String> args = const <String>[]]) => transitions_perf_test.main(
|
||||||
|
<String>['--hybrid', ...args],
|
||||||
|
);
|
@ -153,6 +153,7 @@ Future<void> runDemos(List<String> demos, FlutterDriver driver) async {
|
|||||||
|
|
||||||
void main([List<String> args = const <String>[]]) {
|
void main([List<String> args = const <String>[]]) {
|
||||||
final bool withSemantics = args.contains('--with_semantics');
|
final bool withSemantics = args.contains('--with_semantics');
|
||||||
|
final bool hybrid = args.contains('--hybrid');
|
||||||
group('flutter gallery transitions', () {
|
group('flutter gallery transitions', () {
|
||||||
FlutterDriver driver;
|
FlutterDriver driver;
|
||||||
setUpAll(() async {
|
setUpAll(() async {
|
||||||
@ -186,7 +187,11 @@ void main([List<String> args = const <String>[]]) {
|
|||||||
// Collect timeline data for just a limited set of demos to avoid OOMs.
|
// Collect timeline data for just a limited set of demos to avoid OOMs.
|
||||||
final Timeline timeline = await driver.traceAction(
|
final Timeline timeline = await driver.traceAction(
|
||||||
() async {
|
() async {
|
||||||
await runDemos(kProfiledDemos, driver);
|
if (hybrid) {
|
||||||
|
await driver.requestData('profileDemos');
|
||||||
|
} else {
|
||||||
|
await runDemos(kProfiledDemos, driver);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
streams: const <TimelineStream>[
|
streams: const <TimelineStream>[
|
||||||
TimelineStream.dart,
|
TimelineStream.dart,
|
||||||
@ -205,8 +210,12 @@ void main([List<String> args = const <String>[]]) {
|
|||||||
histogramPath);
|
histogramPath);
|
||||||
|
|
||||||
// Execute the remaining tests.
|
// Execute the remaining tests.
|
||||||
final Set<String> unprofiledDemos = Set<String>.from(_allDemos)..removeAll(kProfiledDemos);
|
if (hybrid) {
|
||||||
await runDemos(unprofiledDemos.toList(), driver);
|
await driver.requestData('profileDemos');
|
||||||
|
} else {
|
||||||
|
final Set<String> unprofiledDemos = Set<String>.from(_allDemos)..removeAll(kProfiledDemos);
|
||||||
|
await runDemos(unprofiledDemos.toList(), driver);
|
||||||
|
}
|
||||||
|
|
||||||
}, timeout: const Timeout(Duration(minutes: 5)));
|
}, timeout: const Timeout(Duration(minutes: 5)));
|
||||||
});
|
});
|
||||||
|
@ -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();
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user