watchPerformance method Null safety
Watches the FrameTiming during action and report it to the binding
with key reportKey.
This can be used to implement performance tests previously using traceAction and TimelineSummary from flutter_driver
Implementation
Future<void> watchPerformance(
Future<void> Function() action, {
String reportKey = 'performance',
}) async {
assert(() {
if (_firstRun) {
debugPrint(kDebugWarning);
_firstRun = false;
}
return true;
}());
// The engine could batch FrameTimings and send them only once per second.
// Delay for a sufficient time so either old FrameTimings are flushed and not
// interfering our measurements here, or new FrameTimings are all reported.
// TODO(CareF): remove this when flush FrameTiming is readly in engine.
// See https://github.com/flutter/flutter/issues/64808
// and https://github.com/flutter/flutter/issues/67593
final List<FrameTiming> frameTimings = <FrameTiming>[];
Future<void> delayForFrameTimings() async {
int count = 0;
while (frameTimings.isEmpty) {
count++;
await Future<void>.delayed(const Duration(seconds: 2));
if (count > 20) {
debugPrint('delayForFrameTimings is taking longer than expected...');
}
}
}
await Future<void>.delayed(const Duration(seconds: 2)); // flush old FrameTimings
final TimingsCallback watcher = frameTimings.addAll;
addTimingsCallback(watcher);
final _GarbageCollectionInfo gcInfo = await _runAndGetGCInfo(action);
await delayForFrameTimings(); // make sure all FrameTimings are reported
removeTimingsCallback(watcher);
final FrameTimingSummarizer frameTimes = FrameTimingSummarizer(
frameTimings,
newGenGCCount: gcInfo.newCount,
oldGenGCCount: gcInfo.oldCount,
);
reportData ??= <String, dynamic>{};
reportData![reportKey] = frameTimes.summary;
}