Unverified Commit ec12ba28 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[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 :)
parent ac095ed3
// 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 'percentile_utils.dart';
import 'timeline.dart';
/// Summarizes [GpuSumarizer]s corresponding to GPU start and end events.
class GpuSumarizer {
/// Creates a RasterCacheSummarizer given the timeline events.
GpuSumarizer(List<TimelineEvent> gpuEvents) {
for (final TimelineEvent event in gpuEvents) {
final Object? value = event.arguments!['FrameTimeMS'];
if (value is String) {
final double? parsedValue = double.tryParse(value);
if (parsedValue != null) {
_frameTimes.add(parsedValue);
}
}
}
}
/// Whether or not this event is a GPU event.
static const Set<String> kGpuEvents = <String>{'GPUTracer'};
final List<double> _frameTimes = <double>[];
/// Computes the average GPU time recorded.
double computeAverageGPUTime() => _computeAverage(_frameTimes);
/// The [percentile]-th percentile GPU time recorded.
double computePercentileGPUTime(double percentile) {
if (_frameTimes.isEmpty) {
return 0;
}
return findPercentile(_frameTimes, percentile);
}
/// Compute the worst GPU time recorded.
double computeWorstGPUTime() => _computeWorst(_frameTimes);
static double _computeAverage(List<double> values) {
if (values.isEmpty) {
return 0;
}
double total = 0;
for (final double data in values) {
total += data;
}
return total / values.length;
}
static double _computeWorst(List<double> values) {
if (values.isEmpty) {
return 0;
}
values.sort();
return values.last;
}
}
......@@ -11,6 +11,7 @@ import 'package:path/path.dart' as path;
import 'common.dart';
import 'frame_request_pending_latency_summarizer.dart';
import 'gc_summarizer.dart';
import 'gpu_sumarizer.dart';
import 'percentile_utils.dart';
import 'profiling_summarizer.dart';
import 'raster_cache_summarizer.dart';
......@@ -275,6 +276,7 @@ class TimelineSummary {
final GCSummarizer gcSummarizer = _gcSummarizer();
final RefreshRateSummary refreshRateSummary = RefreshRateSummary(vsyncEvents: _extractNamedEvents(kUIThreadVsyncProcessEvent));
final FrameRequestPendingLatencySummarizer frameRequestPendingLatencySummarizer = _frameRequestPendingLatencySummarizer();
final GpuSumarizer gpuSummarizer = _gpuSumarizer();
final Map<String, dynamic> timelineSummary = <String, dynamic>{
'average_frame_build_time_millis': computeAverageFrameBuildTimeMillis(),
......@@ -336,6 +338,10 @@ class TimelineSummary {
'90hz_frame_percentage': refreshRateSummary.percentageOf90HzFrames,
'120hz_frame_percentage': refreshRateSummary.percentageOf120HzFrames,
'illegal_refresh_rate_frame_count': refreshRateSummary.framesWithIllegalRefreshRate.length,
'average_gpu_frame_time': gpuSummarizer.computeAverageGPUTime(),
'90th_percentile_gpu_frame_time': gpuSummarizer.computePercentileGPUTime(90.0),
'99th_percentile_gpu_frame_time': gpuSummarizer.computePercentileGPUTime(99.0),
'worst_gpu_frame_time': gpuSummarizer.computeWorstGPUTime(),
};
timelineSummary.addAll(profilingSummary);
......@@ -507,4 +513,6 @@ class TimelineSummary {
FrameRequestPendingLatencySummarizer _frameRequestPendingLatencySummarizer() => FrameRequestPendingLatencySummarizer(_extractNamedEvents(kFrameRequestPendingEvent));
GCSummarizer _gcSummarizer() => GCSummarizer.fromEvents(_extractEventsWithNames(kGCRootEvents));
GpuSumarizer _gpuSumarizer() => GpuSumarizer(_extractEventsWithNames(GpuSumarizer.kGpuEvents));
}
// 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 'package:flutter_driver/flutter_driver.dart';
import 'package:flutter_driver/src/driver/gpu_sumarizer.dart';
import '../common.dart';
TimelineEvent newGPUTraceEvent(double ms) => TimelineEvent(<String, dynamic>{
'name': 'GPUStart',
'ph': 'b',
'args': <String, String>{
'FrameTimeMS': ms.toString()
},
});
void main() {
test('Can process GPU frame times.', () {
final GpuSumarizer summarizer = GpuSumarizer(<TimelineEvent>[
newGPUTraceEvent(4.233),
newGPUTraceEvent(7.22),
newGPUTraceEvent(9.1),
newGPUTraceEvent(40.23),
]);
expect(summarizer.computeAverageGPUTime(), closeTo(15.19, 0.1));
expect(summarizer.computePercentileGPUTime(50.0), closeTo(9.1, 0.1));
expect(summarizer.computeWorstGPUTime(), 40.23);
});
}
......@@ -528,6 +528,10 @@ void main() {
'average_frame_request_pending_latency': 2000.0,
'90th_percentile_frame_request_pending_latency': 3000.0,
'99th_percentile_frame_request_pending_latency': 3000.0,
'average_gpu_frame_time': 0,
'90th_percentile_gpu_frame_time': 0,
'99th_percentile_gpu_frame_time': 0,
'worst_gpu_frame_time': 0,
},
);
});
......@@ -659,6 +663,10 @@ void main() {
'average_frame_request_pending_latency': 2000.0,
'90th_percentile_frame_request_pending_latency': 3000.0,
'99th_percentile_frame_request_pending_latency': 3000.0,
'average_gpu_frame_time': 0,
'90th_percentile_gpu_frame_time': 0,
'99th_percentile_gpu_frame_time': 0,
'worst_gpu_frame_time': 0,
});
});
});
......
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