1use std::time::Duration;
2
3use yscv_eval::{BenchmarkViolation, TimingStats};
4
5#[derive(Debug, Default)]
6pub struct BenchmarkCollector {
7 pub detect: Vec<Duration>,
8 pub track: Vec<Duration>,
9 pub recognize: Vec<Duration>,
10 pub end_to_end: Vec<Duration>,
11}
12
13pub fn format_benchmark_report(report: &yscv_eval::PipelineBenchmarkReport) -> String {
14 let mut output = String::new();
15 output.push_str("benchmark_report_v1\n");
16 output.push_str(&format!("frames={}\n", report.frames));
17 push_stage_stats(&mut output, "detect", &report.detect);
18 push_stage_stats(&mut output, "track", &report.track);
19 push_stage_stats(&mut output, "recognize", &report.recognize);
20 push_stage_stats(&mut output, "end_to_end", &report.end_to_end);
21 output
22}
23
24fn push_stage_stats(output: &mut String, name: &str, stats: &TimingStats) {
25 output.push_str(&format!(
26 "stage={name} runs={} total_ms={:.3} mean_ms={:.3} min_ms={:.3} max_ms={:.3} p50_ms={:.3} p95_ms={:.3} fps={:.3}\n",
27 stats.runs,
28 stats.total_ms,
29 stats.mean_ms,
30 stats.min_ms,
31 stats.max_ms,
32 stats.p50_ms,
33 stats.p95_ms,
34 stats.throughput_fps,
35 ));
36}
37
38pub fn format_benchmark_violations(violations: &[BenchmarkViolation]) -> String {
39 let mut output = String::new();
40 for violation in violations {
41 output.push_str(&format!(
42 " - {}.{} expected {:.3}, observed {:.3}\n",
43 violation.stage, violation.metric, violation.expected, violation.observed
44 ));
45 }
46 output
47}