2026-05-14 18:14:37 +02:00
|
|
|
//! Small helper for best / mean / stdev over wall-time samples.
|
|
|
|
|
//!
|
|
|
|
|
//! We report both best-of-N (the figure that strips OS noise and matches what most
|
|
|
|
|
//! bench READMEs print) and mean +/- stdev (the figure the fee model wants, since
|
|
|
|
|
//! it cares about the steady-state cost not a single fastest sample).
|
|
|
|
|
|
2026-05-18 16:37:11 +02:00
|
|
|
use std::fmt;
|
|
|
|
|
|
2026-05-14 18:14:37 +02:00
|
|
|
use serde::Serialize;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Clone, Copy, Default)]
|
|
|
|
|
pub struct Stats {
|
2026-05-18 16:37:11 +02:00
|
|
|
/// Number of samples in the aggregate (excluding warmup).
|
2026-05-14 18:14:37 +02:00
|
|
|
pub n: usize,
|
2026-05-18 16:37:11 +02:00
|
|
|
/// Lowest sample (ms). Strips OS jitter; matches the bench README "best of N" figure.
|
2026-05-14 18:14:37 +02:00
|
|
|
pub best_ms: f64,
|
2026-05-18 16:37:11 +02:00
|
|
|
/// Arithmetic mean of samples (ms).
|
2026-05-14 18:14:37 +02:00
|
|
|
pub mean_ms: f64,
|
2026-05-18 16:37:11 +02:00
|
|
|
/// Sample standard deviation of samples (ms), computed with Bessel's correction (n-1).
|
|
|
|
|
/// 0.0 when n < 2.
|
2026-05-14 18:14:37 +02:00
|
|
|
pub stdev_ms: f64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Stats {
|
|
|
|
|
pub fn from_samples(samples: &[f64]) -> Self {
|
|
|
|
|
let n = samples.len();
|
|
|
|
|
if n == 0 {
|
|
|
|
|
return Self::default();
|
|
|
|
|
}
|
|
|
|
|
let best_ms = samples.iter().copied().fold(f64::INFINITY, f64::min);
|
|
|
|
|
let sum: f64 = samples.iter().sum();
|
|
|
|
|
let mean_ms = sum / n as f64;
|
|
|
|
|
let stdev_ms = if n > 1 {
|
|
|
|
|
let var: f64 = samples
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|s| {
|
|
|
|
|
let d = s - mean_ms;
|
|
|
|
|
d * d
|
|
|
|
|
})
|
|
|
|
|
.sum::<f64>()
|
|
|
|
|
/ (n - 1) as f64;
|
|
|
|
|
var.sqrt()
|
|
|
|
|
} else {
|
|
|
|
|
0.0
|
|
|
|
|
};
|
|
|
|
|
Self {
|
|
|
|
|
n,
|
|
|
|
|
best_ms,
|
|
|
|
|
mean_ms,
|
|
|
|
|
stdev_ms,
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-05-18 16:37:11 +02:00
|
|
|
}
|
2026-05-14 18:14:37 +02:00
|
|
|
|
2026-05-18 16:37:11 +02:00
|
|
|
/// `best / mean ± stdev (n=N)` for table display.
|
|
|
|
|
impl fmt::Display for Stats {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
2026-05-14 18:14:37 +02:00
|
|
|
"{:.2} / {:.2} ± {:.2} (n={})",
|
|
|
|
|
self.best_ms, self.mean_ms, self.stdev_ms, self.n,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|