mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[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 :)
This commit is contained in:
parent
ac095ed393
commit
ec12ba2875
62
packages/flutter_driver/lib/src/driver/gpu_sumarizer.dart
Normal file
62
packages/flutter_driver/lib/src/driver/gpu_sumarizer.dart
Normal file
@ -0,0 +1,62 @@
|
||||
// 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));
|
||||
}
|
||||
|
31
packages/flutter_driver/test/src/gpu_summarizer_test.dart
Normal file
31
packages/flutter_driver/test/src/gpu_summarizer_test.dart
Normal file
@ -0,0 +1,31 @@
|
||||
// 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,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user