[Impeller] measure GPU memory usage. (#144575)

Framework side to https://github.com/flutter/engine/pull/51187

Part of https://github.com/flutter/flutter/issues/144617
This commit is contained in:
Jonah Williams 2024-03-06 12:17:31 -08:00 committed by GitHub
parent 0df2200b80
commit 2ebd7f0d55
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 115 additions and 0 deletions

View file

@ -1451,10 +1451,16 @@ class PerfTest {
if (data['120hz_frame_percentage'] != null) '120hz_frame_percentage',
if (data['illegal_refresh_rate_frame_count'] != null) 'illegal_refresh_rate_frame_count',
if (recordGPU) ...<String>[
// GPU Frame Time.
if (data['average_gpu_frame_time'] != null) 'average_gpu_frame_time',
if (data['90th_percentile_gpu_frame_time'] != null) '90th_percentile_gpu_frame_time',
if (data['99th_percentile_gpu_frame_time'] != null) '99th_percentile_gpu_frame_time',
if (data['worst_gpu_frame_time'] != null) 'worst_gpu_frame_time',
// GPU Memory.
if (data['average_gpu_memory_mb'] != null) 'average_gpu_memory_mb',
if (data['90th_percentile_gpu_memory_mb'] != null) '90th_percentile_gpu_memory_mb',
if (data['99th_percentile_gpu_memory_mb'] != null) '99th_percentile_gpu_memory_mb',
if (data['worst_gpu_memory_mb'] != null) 'worst_gpu_memory_mb',
]
],
);

View 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 GPU/Device Memory allocations performed by Impeller.
class GPUMemorySumarizer {
/// Creates a RasterCacheSummarizer given the timeline events.
GPUMemorySumarizer(List<TimelineEvent> gpuEvents) {
for (final TimelineEvent event in gpuEvents) {
final Object? value = event.arguments!['MemoryBudgetUsageMB'];
if (value is String) {
final double? parsedValue = double.tryParse(value);
if (parsedValue != null) {
_memoryMB.add(parsedValue);
}
}
}
}
/// Whether or not this event is a GPU allocation event.
static const Set<String> kMemoryEvents = <String>{'AllocatorVK'};
final List<double> _memoryMB = <double>[];
/// Computes the average GPU memory allocated.
double computeAverageMemoryUsage() => _computeAverage(_memoryMB);
/// The [percentile]-th percentile GPU memory allocated.
double computePercentileMemoryUsage(double percentile) {
if (_memoryMB.isEmpty) {
return 0;
}
return findPercentile(_memoryMB, percentile);
}
/// Compute the worst allocation quantity recorded.
double computeWorstMemoryUsage() => _computeWorst(_memoryMB);
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;
}
}

View file

@ -12,6 +12,7 @@ import 'common.dart';
import 'frame_request_pending_latency_summarizer.dart';
import 'gc_summarizer.dart';
import 'gpu_sumarizer.dart';
import 'memory_summarizer.dart';
import 'percentile_utils.dart';
import 'profiling_summarizer.dart';
import 'raster_cache_summarizer.dart';
@ -277,6 +278,7 @@ class TimelineSummary {
final RefreshRateSummary refreshRateSummary = RefreshRateSummary(vsyncEvents: _extractNamedEvents(kUIThreadVsyncProcessEvent));
final FrameRequestPendingLatencySummarizer frameRequestPendingLatencySummarizer = _frameRequestPendingLatencySummarizer();
final GpuSumarizer gpuSummarizer = _gpuSumarizer();
final GPUMemorySumarizer memorySumarizer = _memorySummarizer();
final Map<String, dynamic> timelineSummary = <String, dynamic>{
'average_frame_build_time_millis': computeAverageFrameBuildTimeMillis(),
@ -342,6 +344,10 @@ class TimelineSummary {
'90th_percentile_gpu_frame_time': gpuSummarizer.computePercentileGPUTime(90.0),
'99th_percentile_gpu_frame_time': gpuSummarizer.computePercentileGPUTime(99.0),
'worst_gpu_frame_time': gpuSummarizer.computeWorstGPUTime(),
'average_gpu_memory_mb': memorySumarizer.computeAverageMemoryUsage(),
'90th_percentile_gpu_memory_mb': memorySumarizer.computePercentileMemoryUsage(90.0),
'99th_percentile_gpu_memory_mb': memorySumarizer.computePercentileMemoryUsage(99.0),
'worst_gpu_memory_mb': memorySumarizer.computeWorstMemoryUsage(),
};
timelineSummary.addAll(profilingSummary);
@ -501,4 +507,6 @@ class TimelineSummary {
GCSummarizer _gcSummarizer() => GCSummarizer.fromEvents(_extractEventsWithNames(kGCRootEvents));
GpuSumarizer _gpuSumarizer() => GpuSumarizer(_extractEventsWithNames(GpuSumarizer.kGpuEvents));
GPUMemorySumarizer _memorySummarizer() => GPUMemorySumarizer(_extractEventsWithNames(GPUMemorySumarizer.kMemoryEvents));
}

View 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/memory_summarizer.dart';
import '../common.dart';
TimelineEvent newGPUTraceEvent(double ms) => TimelineEvent(<String, dynamic>{
'name': 'AllocatorVK',
'ph': 'b',
'args': <String, String>{
'MemoryBudgetUsageMB': ms.toString()
},
});
void main() {
test('Can process GPU memory usage times.', () {
final GPUMemorySumarizer summarizer = GPUMemorySumarizer(<TimelineEvent>[
newGPUTraceEvent(1024),
newGPUTraceEvent(1024),
newGPUTraceEvent(512),
newGPUTraceEvent(2048),
]);
expect(summarizer.computeAverageMemoryUsage(), closeTo(1152, 0.1));
expect(summarizer.computePercentileMemoryUsage(50.0), closeTo(1024, 0.1));
expect(summarizer.computeWorstMemoryUsage(), 2048);
});
}

View file

@ -532,6 +532,10 @@ void main() {
'90th_percentile_gpu_frame_time': 0,
'99th_percentile_gpu_frame_time': 0,
'worst_gpu_frame_time': 0,
'average_gpu_memory_mb': 0,
'90th_percentile_gpu_memory_mb': 0,
'99th_percentile_gpu_memory_mb': 0,
'worst_gpu_memory_mb': 0,
},
);
});
@ -667,6 +671,10 @@ void main() {
'90th_percentile_gpu_frame_time': 0,
'99th_percentile_gpu_frame_time': 0,
'worst_gpu_frame_time': 0,
'average_gpu_memory_mb': 0,
'90th_percentile_gpu_memory_mb': 0,
'99th_percentile_gpu_memory_mb': 0,
'worst_gpu_memory_mb': 0,
});
});
});