watchPerformance method
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 readily 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;
}