use std::fmt::Write as FmtWrite;
use std::time::{Duration, Instant};
pub mod colors {
pub const RESET: &str = "\x1b[0m";
pub const BOLD: &str = "\x1b[1m";
pub const DIM: &str = "\x1b[2m";
pub const UNDERLINE: &str = "\x1b[4m";
pub const GREEN: &str = "\x1b[32m";
pub const YELLOW: &str = "\x1b[33m";
pub const RED: &str = "\x1b[31m";
pub const BLUE: &str = "\x1b[34m";
pub const CYAN: &str = "\x1b[36m";
pub const MAGENTA: &str = "\x1b[35m";
pub const WHITE: &str = "\x1b[37m";
pub const BRIGHT_GREEN: &str = "\x1b[92m";
pub const BRIGHT_YELLOW: &str = "\x1b[93m";
pub const BRIGHT_RED: &str = "\x1b[91m";
pub const BRIGHT_CYAN: &str = "\x1b[96m";
pub const BG_GREEN: &str = "\x1b[42m";
pub const BG_RED: &str = "\x1b[41m";
pub const BG_YELLOW: &str = "\x1b[43m";
}
#[derive(Debug, Clone)]
pub struct BenchConfig {
pub iterations: usize,
pub warmup_iterations: usize,
pub outlier_threshold: f64,
pub colors: bool,
pub confidence_level: f64,
}
impl Default for BenchConfig {
fn default() -> Self {
Self {
iterations: 10,
warmup_iterations: 3,
outlier_threshold: 2.0,
colors: true,
confidence_level: 0.95,
}
}
}
#[derive(Debug, Clone)]
pub struct BenchStats {
pub samples: Vec<f64>,
pub mean: f64,
pub std_dev: f64,
pub min: f64,
pub max: f64,
pub median: f64,
pub ci_95: (f64, f64),
pub outliers: usize,
pub cv: f64,
}
impl BenchStats {
pub fn from_samples(mut samples: Vec<f64>, outlier_threshold: f64) -> Self {
if samples.is_empty() {
return Self {
samples: vec![],
mean: 0.0,
std_dev: 0.0,
min: 0.0,
max: 0.0,
median: 0.0,
ci_95: (0.0, 0.0),
outliers: 0,
cv: 0.0,
};
}
samples.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
let n = samples.len() as f64;
let mean = samples.iter().sum::<f64>() / n;
let variance = samples.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / n;
let std_dev = variance.sqrt();
let min = samples.first().copied().unwrap_or(0.0);
let max = samples.last().copied().unwrap_or(0.0);
let median = if samples.len().is_multiple_of(2) {
let mid = samples.len() / 2;
f64::midpoint(samples[mid - 1], samples[mid])
} else {
samples[samples.len() / 2]
};
let t_value = if samples.len() >= 30 { 1.96 } else { 2.0 };
let margin = t_value * std_dev / n.sqrt();
let ci_95 = (mean - margin, mean + margin);
let outliers = samples
.iter()
.filter(|&&x| (x - mean).abs() > outlier_threshold * std_dev)
.count();
let cv = if mean > 0.0 { std_dev / mean } else { 0.0 };
Self {
samples,
mean,
std_dev,
min,
max,
median,
ci_95,
outliers,
cv,
}
}
pub fn format_criterion(&self, name: &str, unit: &str, colors: bool) -> String {
let (green, yellow, red, bold, dim, reset) = if colors {
(
colors::GREEN,
colors::YELLOW,
colors::RED,
colors::BOLD,
colors::DIM,
colors::RESET,
)
} else {
("", "", "", "", "", "")
};
let cv_color = if self.cv < 0.05 {
green
} else if self.cv < 0.10 {
yellow
} else {
red
};
format!(
"{}{:24}{} {:>10.2} {} {dim}[{:.2} {:.2}]{reset} {cv_color}CV={:.1}%{reset}",
bold,
name,
reset,
self.mean,
unit,
self.ci_95.0,
self.ci_95.1,
self.cv * 100.0
)
}
}
#[derive(Debug, Clone)]
pub struct BenchMeasurement {
pub engine: String,
pub format: String,
pub throughput_samples: Vec<f64>,
pub ttft_samples: Vec<f64>,
pub throughput_stats: Option<BenchStats>,
pub ttft_stats: Option<BenchStats>,
pub gpu_util: Option<f64>,
pub gpu_mem_mb: Option<f64>,
}
impl BenchMeasurement {
pub fn new(engine: &str, format: &str) -> Self {
Self {
engine: engine.to_string(),
format: format.to_string(),
throughput_samples: Vec::new(),
ttft_samples: Vec::new(),
throughput_stats: None,
ttft_stats: None,
gpu_util: None,
gpu_mem_mb: None,
}
}
pub fn add_throughput_sample(&mut self, tps: f64) {
self.throughput_samples.push(tps);
}
pub fn add_ttft_sample(&mut self, ttft_ms: f64) {
self.ttft_samples.push(ttft_ms);
}
#[must_use]
pub fn with_throughput(mut self, tps: f64) -> Self {
self.throughput_samples = vec![tps];
self
}
#[must_use]
pub fn with_throughput_samples(mut self, samples: Vec<f64>) -> Self {
self.throughput_samples = samples;
self
}
#[must_use]
pub fn with_ttft(mut self, ttft_ms: f64) -> Self {
self.ttft_samples = vec![ttft_ms];
self
}
#[must_use]
pub fn with_ttft_samples(mut self, samples: Vec<f64>) -> Self {
self.ttft_samples = samples;
self
}
#[must_use]
pub fn with_gpu(mut self, util: f64, mem_mb: f64) -> Self {
self.gpu_util = Some(util);
self.gpu_mem_mb = Some(mem_mb);
self
}
pub fn compute_stats(&mut self, outlier_threshold: f64) {
if !self.throughput_samples.is_empty() {
self.throughput_stats = Some(BenchStats::from_samples(
self.throughput_samples.clone(),
outlier_threshold,
));
}
if !self.ttft_samples.is_empty() {
self.ttft_stats = Some(BenchStats::from_samples(
self.ttft_samples.clone(),
outlier_threshold,
));
}
}
pub fn mean_throughput(&self) -> f64 {
self.throughput_stats.as_ref().map_or_else(
|| {
if self.throughput_samples.is_empty() {
0.0
} else {
self.throughput_samples.iter().sum::<f64>()
/ self.throughput_samples.len() as f64
}
},
|s| s.mean,
)
}
pub fn mean_ttft(&self) -> f64 {
self.ttft_stats.as_ref().map_or_else(
|| {
if self.ttft_samples.is_empty() {
0.0
} else {
self.ttft_samples.iter().sum::<f64>() / self.ttft_samples.len() as f64
}
},
|s| s.mean,
)
}
}
#[derive(Debug, Clone)]
pub struct ProfilingHotspot {
pub component: String,
pub time: Duration,
pub percentage: f64,
pub call_count: u64,
pub avg_per_call: Duration,
pub explanation: String,
pub is_expected: bool,
}
impl ProfilingHotspot {
pub fn to_line(&self, use_colors: bool) -> String {
let (green, yellow, reset) = if use_colors {
(colors::GREEN, colors::YELLOW, colors::RESET)
} else {
("", "", "")
};
let marker = if self.is_expected {
format!("{}✓{}", green, reset)
} else {
format!("{}⚠{}", yellow, reset)
};
format!(
"{} {:20} {:>6.1}% {:>8.2}ms ({:>6} calls, {:>6.2}us/call)",
marker,
self.component,
self.percentage,
self.time.as_secs_f64() * 1000.0,
self.call_count,
self.avg_per_call.as_secs_f64() * 1_000_000.0
)
}
}
include!("benchmark_grid.rs");
include!("grid_impl.rs");
include!("benchmark_runner.rs");