Unverified Commit 304b9c66 authored by Dan Field's avatar Dan Field Committed by GitHub

Reland GC tracking benchmarks (#82069)

parent 9805df89
...@@ -6,7 +6,7 @@ import 'package:flutter_driver/flutter_driver.dart'; ...@@ -6,7 +6,7 @@ import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart' hide TypeMatcher, isInstanceOf; import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
Future<void> main() async { Future<void> main() async {
const String fileName = 'large_image_changer'; const String fileName = 'animated_image';
test('Animate for 250 frames', () async { test('Animate for 250 frames', () async {
final FlutterDriver driver = await FlutterDriver.connect(); final FlutterDriver driver = await FlutterDriver.connect();
......
...@@ -9,8 +9,11 @@ import 'package:flutter_devicelab/tasks/perf_tests.dart'; ...@@ -9,8 +9,11 @@ import 'package:flutter_devicelab/tasks/perf_tests.dart';
Future<void> main() async { Future<void> main() async {
deviceOperatingSystem = DeviceOperatingSystem.android; deviceOperatingSystem = DeviceOperatingSystem.android;
await task(DevToolsMemoryTest( await task(PerfTest(
'${flutterDirectory.path}/dev/benchmarks/macrobenchmarks', '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
'test_driver/animated_image.dart', 'test_driver/animated_image.dart',
'animated_image',
measureCpuGpu: true,
measureMemory: true,
).run); ).run);
} }
...@@ -87,6 +87,7 @@ class GalleryTransitionTest { ...@@ -87,6 +87,7 @@ class GalleryTransitionTest {
: '${testFile}_test'); : '${testFile}_test');
section('DRIVE START'); section('DRIVE START');
await flutter('drive', options: <String>[ await flutter('drive', options: <String>[
'--no-dds',
'--profile', '--profile',
if (needFullTimeline) if (needFullTimeline)
'--trace-startup', '--trace-startup',
......
...@@ -705,6 +705,7 @@ class PerfTest { ...@@ -705,6 +705,7 @@ class PerfTest {
final String deviceId = device.deviceId; final String deviceId = device.deviceId;
await flutter('drive', options: <String>[ await flutter('drive', options: <String>[
'--no-dds', // TODO(dnfield): consider removing when https://github.com/flutter/flutter/issues/81707 is fixed
'--no-android-gradle-daemon', '--no-android-gradle-daemon',
'-v', '-v',
'--verbose-system-logs', '--verbose-system-logs',
...@@ -777,6 +778,8 @@ const List<String> _kCommonScoreKeys = <String>[ ...@@ -777,6 +778,8 @@ const List<String> _kCommonScoreKeys = <String>[
'worst_frame_rasterizer_time_millis', 'worst_frame_rasterizer_time_millis',
'90th_percentile_frame_rasterizer_time_millis', '90th_percentile_frame_rasterizer_time_millis',
'99th_percentile_frame_rasterizer_time_millis', '99th_percentile_frame_rasterizer_time_millis',
'new_gen_gc_count',
'old_gen_gc_count',
]; ];
class PerfTestWithSkSL extends PerfTest { class PerfTestWithSkSL extends PerfTest {
...@@ -868,6 +871,7 @@ class PerfTestWithSkSL extends PerfTest { ...@@ -868,6 +871,7 @@ class PerfTestWithSkSL extends PerfTest {
_flutterPath, _flutterPath,
<String>[ <String>[
'run', 'run',
'--no-dds',
if (deviceOperatingSystem == DeviceOperatingSystem.ios) if (deviceOperatingSystem == DeviceOperatingSystem.ios)
...<String>[ ...<String>[
'--device-timeout', '5', '--device-timeout', '5',
......
...@@ -17,7 +17,11 @@ class FrameTimingSummarizer { ...@@ -17,7 +17,11 @@ class FrameTimingSummarizer {
/// Summarize `data` to frame build time and frame rasterizer time statistics. /// Summarize `data` to frame build time and frame rasterizer time statistics.
/// ///
/// See [TimelineSummary.summaryJson] for detail. /// See [TimelineSummary.summaryJson] for detail.
factory FrameTimingSummarizer(List<FrameTiming> data) { factory FrameTimingSummarizer(
List<FrameTiming> data, {
int? newGenGCCount,
int? oldGenGCCount,
}) {
assert(data != null); assert(data != null);
assert(data.isNotEmpty); assert(data.isNotEmpty);
final List<Duration> frameBuildTime = List<Duration>.unmodifiable( final List<Duration> frameBuildTime = List<Duration>.unmodifiable(
...@@ -58,6 +62,8 @@ class FrameTimingSummarizer { ...@@ -58,6 +62,8 @@ class FrameTimingSummarizer {
p90VsyncOverhead: _findPercentile(vsyncOverheadSorted, 0.90), p90VsyncOverhead: _findPercentile(vsyncOverheadSorted, 0.90),
p99VsyncOverhead: _findPercentile(vsyncOverheadSorted, 0.99), p99VsyncOverhead: _findPercentile(vsyncOverheadSorted, 0.99),
worstVsyncOverhead: vsyncOverheadSorted.last, worstVsyncOverhead: vsyncOverheadSorted.last,
newGenGCCount: newGenGCCount ?? -1,
oldGenGCCount: oldGenGCCount ?? -1,
); );
} }
...@@ -79,6 +85,8 @@ class FrameTimingSummarizer { ...@@ -79,6 +85,8 @@ class FrameTimingSummarizer {
required this.p90VsyncOverhead, required this.p90VsyncOverhead,
required this.p99VsyncOverhead, required this.p99VsyncOverhead,
required this.worstVsyncOverhead, required this.worstVsyncOverhead,
required this.newGenGCCount,
required this.oldGenGCCount,
}); });
/// List of frame build time in microseconds /// List of frame build time in microseconds
...@@ -133,6 +141,12 @@ class FrameTimingSummarizer { ...@@ -133,6 +141,12 @@ class FrameTimingSummarizer {
/// The largest value of [vsyncOverhead] in milliseconds. /// The largest value of [vsyncOverhead] in milliseconds.
final Duration worstVsyncOverhead; final Duration worstVsyncOverhead;
/// The number of new generation GCs.
final int newGenGCCount;
/// The number of old generation GCs.
final int oldGenGCCount;
/// Convert the summary result to a json object. /// Convert the summary result to a json object.
/// ///
/// See [TimelineSummary.summaryJson] for detail. /// See [TimelineSummary.summaryJson] for detail.
...@@ -162,6 +176,8 @@ class FrameTimingSummarizer { ...@@ -162,6 +176,8 @@ class FrameTimingSummarizer {
'frame_rasterizer_times': frameRasterizerTime 'frame_rasterizer_times': frameRasterizerTime
.map<int>((Duration datum) => datum.inMicroseconds) .map<int>((Duration datum) => datum.inMicroseconds)
.toList(), .toList(),
'new_gen_gc_count': newGenGCCount,
'old_gen_gc_count': oldGenGCCount,
}; };
} }
......
...@@ -228,8 +228,7 @@ https://flutter.dev/docs/testing/integration-tests#testing-on-firebase-test-lab ...@@ -228,8 +228,7 @@ https://flutter.dev/docs/testing/integration-tests#testing-on-firebase-test-lab
_vmService = vmService; _vmService = vmService;
} }
if (_vmService == null) { if (_vmService == null) {
final developer.ServiceProtocolInfo info = final developer.ServiceProtocolInfo info = await developer.Service.getInfo();
await developer.Service.getInfo();
assert(info.serverUri != null); assert(info.serverUri != null);
_vmService = await vm_io.vmServiceConnectUri( _vmService = await vm_io.vmServiceConnectUri(
'ws://localhost:${info.serverUri!.port}${info.serverUri!.path}ws', 'ws://localhost:${info.serverUri!.port}${info.serverUri!.path}ws',
...@@ -302,6 +301,29 @@ https://flutter.dev/docs/testing/integration-tests#testing-on-firebase-test-lab ...@@ -302,6 +301,29 @@ https://flutter.dev/docs/testing/integration-tests#testing-on-firebase-test-lab
reportData![reportKey] = timeline.toJson(); reportData![reportKey] = timeline.toJson();
} }
Future<_GarbageCollectionInfo> _runAndGetGCInfo(Future<void> Function() action) async {
if (kIsWeb) {
await action();
return const _GarbageCollectionInfo();
}
final vm.Timeline timeline = await traceTimeline(
action,
streams: <String>['GC'],
);
final int oldGenGCCount = timeline.traceEvents!.where((vm.TimelineEvent event) {
return event.json!['cat'] == 'GC' && event.json!['name'] == 'CollectOldGeneration';
}).length;
final int newGenGCCount = timeline.traceEvents!.where((vm.TimelineEvent event) {
return event.json!['cat'] == 'GC' && event.json!['name'] == 'CollectNewGeneration';
}).length;
return _GarbageCollectionInfo(
oldCount: oldGenGCCount,
newCount: newGenGCCount,
);
}
/// Watches the [FrameTiming] during `action` and report it to the binding /// Watches the [FrameTiming] during `action` and report it to the binding
/// with key `reportKey`. /// with key `reportKey`.
/// ///
...@@ -340,11 +362,16 @@ https://flutter.dev/docs/testing/integration-tests#testing-on-firebase-test-lab ...@@ -340,11 +362,16 @@ https://flutter.dev/docs/testing/integration-tests#testing-on-firebase-test-lab
await Future<void>.delayed(const Duration(seconds: 2)); // flush old FrameTimings await Future<void>.delayed(const Duration(seconds: 2)); // flush old FrameTimings
final TimingsCallback watcher = frameTimings.addAll; final TimingsCallback watcher = frameTimings.addAll;
addTimingsCallback(watcher); addTimingsCallback(watcher);
await action(); final _GarbageCollectionInfo gcInfo = await _runAndGetGCInfo(action);
await delayForFrameTimings(); // make sure all FrameTimings are reported await delayForFrameTimings(); // make sure all FrameTimings are reported
removeTimingsCallback(watcher); removeTimingsCallback(watcher);
final FrameTimingSummarizer frameTimes =
FrameTimingSummarizer(frameTimings); final FrameTimingSummarizer frameTimes = FrameTimingSummarizer(
frameTimings,
newGenGCCount: gcInfo.newCount,
oldGenGCCount: gcInfo.oldCount,
);
reportData ??= <String, dynamic>{}; reportData ??= <String, dynamic>{};
reportData![reportKey] = frameTimes.summary; reportData![reportKey] = frameTimes.summary;
} }
...@@ -381,3 +408,11 @@ https://flutter.dev/docs/testing/integration-tests#testing-on-firebase-test-lab ...@@ -381,3 +408,11 @@ https://flutter.dev/docs/testing/integration-tests#testing-on-firebase-test-lab
// `LiveTestWidgetsFlutterBinding` https://github.com/flutter/flutter/issues/81534 // `LiveTestWidgetsFlutterBinding` https://github.com/flutter/flutter/issues/81534
} }
} }
@immutable
class _GarbageCollectionInfo {
const _GarbageCollectionInfo({this.oldCount = -1, this.newCount = -1});
final int oldCount;
final int newCount;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment