Files
BadNote/lib/diagnostics/frame_sampler.dart

100 lines
2.2 KiB
Dart
Raw Permalink Normal View History

// Frame / hitch sampler for diagnostic packs.
import 'badnote_log.dart';
class FrameSample {
FrameSample({
required this.at,
required this.label,
required this.ms,
this.dropped = false,
});
final DateTime at;
final String label;
final double ms;
final bool dropped;
Map<String, Object?> toJson() => {
'at': at.toIso8601String(),
'label': label,
'ms': ms,
'dropped': dropped,
};
}
class FrameSampler {
FrameSampler._();
static final FrameSampler instance = FrameSampler._();
static const int capacity = 500;
final List<FrameSample> _samples = <FrameSample>[];
int overBudget = 0;
int total = 0;
/// Budget for a single frame at 60fps.
static const double budgetMs = 16.6;
void record(String label, double ms, {bool dropped = false}) {
total++;
final over = ms > budgetMs;
if (over) overBudget++;
final sample = FrameSample(
at: DateTime.now(),
label: label,
ms: ms,
dropped: dropped || over,
);
_samples.add(sample);
if (_samples.length > capacity) {
_samples.removeRange(0, _samples.length - capacity);
}
if (over || dropped) {
BadNoteLog.instance.warn(
LogSubsystem.frame,
'slow_frame',
fields: {'label': label, 'ms': ms, 'dropped': dropped},
);
}
}
void recordZoom({
required double rawScale,
required bool scaleDrop,
required bool focalDrop,
required double focalJumpPx,
}) {
record(
'zoom',
scaleDrop || focalDrop ? budgetMs + 1 : 8,
dropped: scaleDrop || focalDrop,
);
BadNoteLog.instance.debug(
LogSubsystem.frame,
'zoom',
fields: {
'rawScale': rawScale,
'scaleDrop': scaleDrop,
'focalDrop': focalDrop,
'focalJumpPx': focalJumpPx,
},
);
}
List<Map<String, Object?>> toJsonList() =>
_samples.map((s) => s.toJson()).toList(growable: false);
Map<String, Object?> summary() => {
'total': total,
'overBudget': overBudget,
'budgetMs': budgetMs,
'recent': toJsonList(),
};
void reset() {
_samples.clear();
overBudget = 0;
total = 0;
}
}