use config::Config;
use state::State;
use std::sync::{Once, ONCE_INIT};
static HEADER: Once = ONCE_INIT;
fn should_run_bm(bm_name: &String) -> bool {
let filter = &Config::get().filter;
filter.is_match(bm_name)
}
fn range_generator<T>(i: T) -> T {
i
}
fn compose<T: 'static, U: 'static>(f: Box<Fn(u64) -> T>, g: fn(T) -> U) -> Box<Fn(u64) -> U> {
Box::new(move |i: u64| g(f(i)))
}
pub struct Benchmark<T: 'static + Clone> {
name: &'static str,
fns: Vec<(&'static str, fn(&mut State<T>))>,
range: (u64, u64, u64),
generator: Box<Fn(u64) -> T>,
}
impl Benchmark<u64> {
pub fn with_name(name: &'static str) -> Self {
Benchmark {
name,
fns: Vec::new(),
range: (1, 1 << 20, 2),
generator: Box::new(range_generator),
}
}
}
impl<T: Clone> Benchmark<T> {
pub fn with_lower_bound(mut self, lb: u64) -> Self {
self.range.0 = lb;
self
}
pub fn with_upper_bound(mut self, ub: u64) -> Self {
self.range.1 = ub;
self
}
pub fn with_mul(mut self, mul: u64) -> Self {
self.range.2 = mul;
self
}
pub fn with_range(mut self, lb: u64, ub: u64, mul: u64) -> Self {
self.range = (lb, ub, mul);
self
}
pub fn with_generator<U: Clone>(self, gen: fn(T) -> U) -> Benchmark<U> {
Benchmark {
name: self.name,
fns: Vec::new(),
range: self.range,
generator: compose(self.generator, gen),
}
}
pub fn with_bench(mut self, t: (&'static str, fn(&mut State<T>))) -> Self {
self.fns.push(t);
self
}
pub fn run(self) {
if self.fns.len() == 0 {
panic!("Cannot call run on an empty benchmark");
}
let (lb, ub, mul) = self.range;
let mut i = lb;
let gen = &self.generator;
while i <= ub {
let input = gen(i);
for (name, f) in &self.fns {
let bm_name = format!("{}/{}/{}", self.name, name, i);
if should_run_bm(&bm_name) {
let mut runs = 0;
let mut total_duration = 0;
while runs < Config::get().min_runs as u64
|| total_duration < Config::get().min_duration
{
let mut state = State::new(input.clone());
f(&mut state);
total_duration += state.finish();
runs += 1;
}
HEADER.call_once(|| {
println!("Name,Time (ns)");
});
println!("{},{}", bm_name, total_duration / runs);
}
}
i *= mul;
}
}
}