From abebd8b7b79d4586174d96d0b33ac058916fbfde Mon Sep 17 00:00:00 2001 From: keyonghan <54558023+keyonghan@users.noreply.github.com> Date: Thu, 12 May 2022 09:54:10 -0700 Subject: [PATCH] Separate build and test for `flutter_gallery__transition_perf` task (#103550) --- .../flutter_gallery__transition_perf.dart | 4 +- dev/devicelab/lib/tasks/gallery.dart | 141 ++++++++++++++++++ 2 files changed, 143 insertions(+), 2 deletions(-) diff --git a/dev/devicelab/bin/tasks/flutter_gallery__transition_perf.dart b/dev/devicelab/bin/tasks/flutter_gallery__transition_perf.dart index dde9d8c3d662..869ff2207217 100644 --- a/dev/devicelab/bin/tasks/flutter_gallery__transition_perf.dart +++ b/dev/devicelab/bin/tasks/flutter_gallery__transition_perf.dart @@ -6,7 +6,7 @@ import 'package:flutter_devicelab/framework/devices.dart'; import 'package:flutter_devicelab/framework/framework.dart'; import 'package:flutter_devicelab/tasks/gallery.dart'; -Future main() async { +Future main(List args) async { deviceOperatingSystem = DeviceOperatingSystem.android; - await task(createGalleryTransitionTest()); + await task(createGalleryTransitionBuildTest(args)); } diff --git a/dev/devicelab/lib/tasks/gallery.dart b/dev/devicelab/lib/tasks/gallery.dart index aadb1e59a5ab..4c24622cbb8f 100644 --- a/dev/devicelab/lib/tasks/gallery.dart +++ b/dev/devicelab/lib/tasks/gallery.dart @@ -10,6 +10,16 @@ import '../framework/devices.dart'; import '../framework/framework.dart'; import '../framework/task_result.dart'; import '../framework/utils.dart'; +import 'build_test_task.dart'; + +final Directory galleryDirectory = dir('${flutterDirectory.path}/dev/integration_tests/flutter_gallery'); + +/// Temp function during gallery tests transition to build+test model. +/// +/// https://github.com/flutter/flutter/issues/103542 +TaskFunction createGalleryTransitionBuildTest(List args, {bool semanticsEnabled = false}) { + return GalleryTransitionBuildTest(args, semanticsEnabled: semanticsEnabled); +} TaskFunction createGalleryTransitionTest({bool semanticsEnabled = false}) { return GalleryTransitionTest(semanticsEnabled: semanticsEnabled); @@ -176,6 +186,137 @@ class GalleryTransitionTest { } } +class GalleryTransitionBuildTest extends BuildTestTask { + GalleryTransitionBuildTest( + super.args, { + this.semanticsEnabled = false, + this.testFile = 'transitions_perf', + this.needFullTimeline = true, + this.timelineSummaryFile = 'transitions.timeline_summary', + this.timelineTraceFile = 'transitions.timeline', + this.transitionDurationFile = 'transition_durations.timeline', + this.driverFile, + this.measureCpuGpu = true, + this.measureMemory = true, + }) : super(workingDirectory: galleryDirectory); + + final bool semanticsEnabled; + final bool needFullTimeline; + final bool measureCpuGpu; + final bool measureMemory; + final String testFile; + final String timelineSummaryFile; + final String? timelineTraceFile; + final String? transitionDurationFile; + final String? driverFile; + + final String testOutputDirectory = Platform.environment['FLUTTER_TEST_OUTPUTS_DIR'] ?? '${galleryDirectory.path}/build'; + + @override + List getBuildArgs(DeviceOperatingSystem deviceOperatingSystem) { + return [ + 'apk', + '--no-android-gradle-daemon', + '--profile', + '-t', + 'test_driver/$testFile.dart', + '--target-platform', + 'android-arm,android-arm64', + ]; + } + + @override + List getTestArgs(DeviceOperatingSystem deviceOperatingSystem, String deviceId) { + final String testDriver = driverFile ?? (semanticsEnabled ? '${testFile}_with_semantics_test' : '${testFile}_test'); + return [ + '--profile', + if (needFullTimeline) '--trace-startup', + '-t', + 'test_driver/$testFile.dart', + '--use-application-binary=${getApplicationBinaryPath()}', + '--driver', + 'test_driver/$testDriver.dart', + '-d', + deviceId, + ]; + } + + @override + Future parseTaskResult() async { + final Map summary = json.decode( + file('$testOutputDirectory/$timelineSummaryFile.json').readAsStringSync(), + ) as Map; + + if (transitionDurationFile != null) { + final Map original = json.decode( + file('$testOutputDirectory/$transitionDurationFile.json').readAsStringSync(), + ) as Map; + final Map> transitions = >{}; + for (final String key in original.keys) { + transitions[key] = List.from(original[key] as List); + } + summary['transitions'] = transitions; + summary['missed_transition_count'] = _countMissedTransitions(transitions); + } + + final bool isAndroid = deviceOperatingSystem == DeviceOperatingSystem.android; + return TaskResult.success( + summary, + detailFiles: [ + if (transitionDurationFile != null) '$testOutputDirectory/$transitionDurationFile.json', + if (timelineTraceFile != null) '$testOutputDirectory/$timelineTraceFile.json', + ], + benchmarkScoreKeys: [ + if (transitionDurationFile != null) 'missed_transition_count', + 'average_frame_build_time_millis', + 'worst_frame_build_time_millis', + '90th_percentile_frame_build_time_millis', + '99th_percentile_frame_build_time_millis', + 'average_frame_rasterizer_time_millis', + 'worst_frame_rasterizer_time_millis', + '90th_percentile_frame_rasterizer_time_millis', + '99th_percentile_frame_rasterizer_time_millis', + 'average_layer_cache_count', + '90th_percentile_layer_cache_count', + '99th_percentile_layer_cache_count', + 'worst_layer_cache_count', + 'average_layer_cache_memory', + '90th_percentile_layer_cache_memory', + '99th_percentile_layer_cache_memory', + 'worst_layer_cache_memory', + 'average_picture_cache_count', + '90th_percentile_picture_cache_count', + '99th_percentile_picture_cache_count', + 'worst_picture_cache_count', + 'average_picture_cache_memory', + '90th_percentile_picture_cache_memory', + '99th_percentile_picture_cache_memory', + 'worst_picture_cache_memory', + if (measureCpuGpu && !isAndroid) ...[ + // See https://github.com/flutter/flutter/issues/68888 + if (summary['average_cpu_usage'] != null) 'average_cpu_usage', + if (summary['average_gpu_usage'] != null) 'average_gpu_usage', + ], + if (measureMemory && !isAndroid) ...[ + // See https://github.com/flutter/flutter/issues/68888 + if (summary['average_memory_usage'] != null) 'average_memory_usage', + if (summary['90th_percentile_memory_usage'] != null) '90th_percentile_memory_usage', + if (summary['99th_percentile_memory_usage'] != null) '99th_percentile_memory_usage', + ], + ], + ); + } + + @override + String getApplicationBinaryPath() { + if (applicationBinaryPath != null) { + return applicationBinaryPath!; + } + + return 'build/app/outputs/flutter-apk/app-profile.apk'; + } +} + int _countMissedTransitions(Map> transitions) { const int kTransitionBudget = 100000; // µs int count = 0;