use std::time::Duration;
#[derive(Debug, Clone)]
pub struct BenchmarkConfig {
pub warmup_iterations: usize,
pub measurement_iterations: usize,
pub workload_sizes: Vec<usize>,
pub convergence_threshold: f64,
pub max_iterations: usize,
pub regression_threshold: f64,
pub timeout: Duration,
}
impl Default for BenchmarkConfig {
fn default() -> Self {
Self {
warmup_iterations: 3,
measurement_iterations: 5,
workload_sizes: vec![10_000, 50_000, 100_000],
convergence_threshold: 1e-6,
max_iterations: 100,
regression_threshold: 0.10,
timeout: Duration::from_secs(60),
}
}
}
impl BenchmarkConfig {
#[must_use]
pub fn quick() -> Self {
Self {
warmup_iterations: 1,
measurement_iterations: 3,
workload_sizes: vec![10_000, 50_000],
convergence_threshold: 1e-5,
max_iterations: 50,
regression_threshold: 0.15,
timeout: Duration::from_secs(30),
}
}
#[must_use]
pub fn comprehensive() -> Self {
Self {
warmup_iterations: 5,
measurement_iterations: 10,
workload_sizes: vec![10_000, 25_000, 50_000, 75_000, 100_000, 150_000],
convergence_threshold: 1e-6,
max_iterations: 200,
regression_threshold: 0.05,
timeout: Duration::from_secs(300),
}
}
#[must_use]
pub fn ci() -> Self {
Self {
warmup_iterations: 2,
measurement_iterations: 5,
workload_sizes: vec![10_000, 50_000],
convergence_threshold: 1e-5,
max_iterations: 100,
regression_threshold: 0.10,
timeout: Duration::from_secs(120),
}
}
#[must_use]
pub fn with_warmup(mut self, iterations: usize) -> Self {
self.warmup_iterations = iterations;
self
}
#[must_use]
pub fn with_measurements(mut self, iterations: usize) -> Self {
self.measurement_iterations = iterations;
self
}
#[must_use]
pub fn with_sizes(mut self, sizes: Vec<usize>) -> Self {
self.workload_sizes = sizes;
self
}
#[must_use]
pub fn with_regression_threshold(mut self, threshold: f64) -> Self {
self.regression_threshold = threshold;
self
}
#[must_use]
pub fn with_timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_config_defaults() {
let config = BenchmarkConfig::default();
assert!(!config.workload_sizes.is_empty());
assert!(config.warmup_iterations > 0);
assert!(config.measurement_iterations > 0);
}
#[test]
fn test_config_quick() {
let config = BenchmarkConfig::quick();
assert!(config.measurement_iterations < BenchmarkConfig::default().measurement_iterations);
}
#[test]
fn test_config_comprehensive() {
let config = BenchmarkConfig::comprehensive();
assert!(config.measurement_iterations > BenchmarkConfig::default().measurement_iterations);
}
#[test]
fn test_config_builder() {
let config = BenchmarkConfig::default()
.with_warmup(10)
.with_measurements(20)
.with_sizes(vec![1000, 2000])
.with_regression_threshold(0.05);
assert_eq!(config.warmup_iterations, 10);
assert_eq!(config.measurement_iterations, 20);
assert_eq!(config.workload_sizes, vec![1000, 2000]);
assert!((config.regression_threshold - 0.05).abs() < f64::EPSILON);
}
}