Skip to content

Commit ec12ba2

Browse files
author
Jonah Williams
authored
[Impeller] GPU frame timings summarization. (#136408)
Allow processing GPU start and end events to get processed by flutter driver. To figure out whether or not this works we'll ship in on CI :)
1 parent ac095ed commit ec12ba2

4 files changed

Lines changed: 109 additions & 0 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'percentile_utils.dart';
6+
import 'timeline.dart';
7+
8+
/// Summarizes [GpuSumarizer]s corresponding to GPU start and end events.
9+
class GpuSumarizer {
10+
/// Creates a RasterCacheSummarizer given the timeline events.
11+
GpuSumarizer(List<TimelineEvent> gpuEvents) {
12+
for (final TimelineEvent event in gpuEvents) {
13+
final Object? value = event.arguments!['FrameTimeMS'];
14+
if (value is String) {
15+
final double? parsedValue = double.tryParse(value);
16+
if (parsedValue != null) {
17+
_frameTimes.add(parsedValue);
18+
}
19+
}
20+
}
21+
}
22+
23+
/// Whether or not this event is a GPU event.
24+
static const Set<String> kGpuEvents = <String>{'GPUTracer'};
25+
26+
final List<double> _frameTimes = <double>[];
27+
28+
/// Computes the average GPU time recorded.
29+
double computeAverageGPUTime() => _computeAverage(_frameTimes);
30+
31+
/// The [percentile]-th percentile GPU time recorded.
32+
double computePercentileGPUTime(double percentile) {
33+
if (_frameTimes.isEmpty) {
34+
return 0;
35+
}
36+
return findPercentile(_frameTimes, percentile);
37+
}
38+
39+
/// Compute the worst GPU time recorded.
40+
double computeWorstGPUTime() => _computeWorst(_frameTimes);
41+
42+
static double _computeAverage(List<double> values) {
43+
if (values.isEmpty) {
44+
return 0;
45+
}
46+
47+
double total = 0;
48+
for (final double data in values) {
49+
total += data;
50+
}
51+
return total / values.length;
52+
}
53+
54+
static double _computeWorst(List<double> values) {
55+
if (values.isEmpty) {
56+
return 0;
57+
}
58+
59+
values.sort();
60+
return values.last;
61+
}
62+
}

packages/flutter_driver/lib/src/driver/timeline_summary.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:path/path.dart' as path;
1111
import 'common.dart';
1212
import 'frame_request_pending_latency_summarizer.dart';
1313
import 'gc_summarizer.dart';
14+
import 'gpu_sumarizer.dart';
1415
import 'percentile_utils.dart';
1516
import 'profiling_summarizer.dart';
1617
import 'raster_cache_summarizer.dart';
@@ -275,6 +276,7 @@ class TimelineSummary {
275276
final GCSummarizer gcSummarizer = _gcSummarizer();
276277
final RefreshRateSummary refreshRateSummary = RefreshRateSummary(vsyncEvents: _extractNamedEvents(kUIThreadVsyncProcessEvent));
277278
final FrameRequestPendingLatencySummarizer frameRequestPendingLatencySummarizer = _frameRequestPendingLatencySummarizer();
279+
final GpuSumarizer gpuSummarizer = _gpuSumarizer();
278280

279281
final Map<String, dynamic> timelineSummary = <String, dynamic>{
280282
'average_frame_build_time_millis': computeAverageFrameBuildTimeMillis(),
@@ -336,6 +338,10 @@ class TimelineSummary {
336338
'90hz_frame_percentage': refreshRateSummary.percentageOf90HzFrames,
337339
'120hz_frame_percentage': refreshRateSummary.percentageOf120HzFrames,
338340
'illegal_refresh_rate_frame_count': refreshRateSummary.framesWithIllegalRefreshRate.length,
341+
'average_gpu_frame_time': gpuSummarizer.computeAverageGPUTime(),
342+
'90th_percentile_gpu_frame_time': gpuSummarizer.computePercentileGPUTime(90.0),
343+
'99th_percentile_gpu_frame_time': gpuSummarizer.computePercentileGPUTime(99.0),
344+
'worst_gpu_frame_time': gpuSummarizer.computeWorstGPUTime(),
339345
};
340346

341347
timelineSummary.addAll(profilingSummary);
@@ -507,4 +513,6 @@ class TimelineSummary {
507513
FrameRequestPendingLatencySummarizer _frameRequestPendingLatencySummarizer() => FrameRequestPendingLatencySummarizer(_extractNamedEvents(kFrameRequestPendingEvent));
508514

509515
GCSummarizer _gcSummarizer() => GCSummarizer.fromEvents(_extractEventsWithNames(kGCRootEvents));
516+
517+
GpuSumarizer _gpuSumarizer() => GpuSumarizer(_extractEventsWithNames(GpuSumarizer.kGpuEvents));
510518
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter_driver/flutter_driver.dart';
6+
import 'package:flutter_driver/src/driver/gpu_sumarizer.dart';
7+
8+
import '../common.dart';
9+
10+
TimelineEvent newGPUTraceEvent(double ms) => TimelineEvent(<String, dynamic>{
11+
'name': 'GPUStart',
12+
'ph': 'b',
13+
'args': <String, String>{
14+
'FrameTimeMS': ms.toString()
15+
},
16+
});
17+
18+
void main() {
19+
test('Can process GPU frame times.', () {
20+
final GpuSumarizer summarizer = GpuSumarizer(<TimelineEvent>[
21+
newGPUTraceEvent(4.233),
22+
newGPUTraceEvent(7.22),
23+
newGPUTraceEvent(9.1),
24+
newGPUTraceEvent(40.23),
25+
]);
26+
27+
expect(summarizer.computeAverageGPUTime(), closeTo(15.19, 0.1));
28+
expect(summarizer.computePercentileGPUTime(50.0), closeTo(9.1, 0.1));
29+
expect(summarizer.computeWorstGPUTime(), 40.23);
30+
});
31+
}

packages/flutter_driver/test/src/real_tests/timeline_summary_test.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,10 @@ void main() {
528528
'average_frame_request_pending_latency': 2000.0,
529529
'90th_percentile_frame_request_pending_latency': 3000.0,
530530
'99th_percentile_frame_request_pending_latency': 3000.0,
531+
'average_gpu_frame_time': 0,
532+
'90th_percentile_gpu_frame_time': 0,
533+
'99th_percentile_gpu_frame_time': 0,
534+
'worst_gpu_frame_time': 0,
531535
},
532536
);
533537
});
@@ -659,6 +663,10 @@ void main() {
659663
'average_frame_request_pending_latency': 2000.0,
660664
'90th_percentile_frame_request_pending_latency': 3000.0,
661665
'99th_percentile_frame_request_pending_latency': 3000.0,
666+
'average_gpu_frame_time': 0,
667+
'90th_percentile_gpu_frame_time': 0,
668+
'99th_percentile_gpu_frame_time': 0,
669+
'worst_gpu_frame_time': 0,
662670
});
663671
});
664672
});

0 commit comments

Comments
 (0)