use criterion::{criterion_group, criterion_main, Criterion}; use itertools::{Itertools, cloned}; trait IterEx : Iterator { // Another efficient implementation against which to compare, // but needs `std` so is less desirable. fn tree_fold1_vec(self, mut f: F) -> Option where F: FnMut(Self::Item, Self::Item) -> Self::Item, Self: Sized, { let hint = self.size_hint().0; let cap = std::mem::size_of::() * 8 - hint.leading_zeros() as usize; let mut stack = Vec::with_capacity(cap); self.enumerate().for_each(|(mut i, mut x)| { while (i & 1) != 0 { x = f(stack.pop().unwrap(), x); i >>= 1; } stack.push(x); }); stack.into_iter().fold1(f) } } impl IterEx for T {} macro_rules! def_benchs { ($N:expr, $FUN:ident, $BENCH_NAME:ident, ) => ( mod $BENCH_NAME { use super::*; pub fn sum(c: &mut Criterion) { let v: Vec = (0.. $N).collect(); c.bench_function(&(stringify!($BENCH_NAME).replace('_', " ") + " sum"), move |b| { b.iter(|| { cloned(&v).$FUN(|x, y| x + y) }) }); } pub fn complex_iter(c: &mut Criterion) { let u = (3..).take($N / 2); let v = (5..).take($N / 2); let it = u.chain(v); c.bench_function(&(stringify!($BENCH_NAME).replace('_', " ") + " complex iter"), move |b| { b.iter(|| { it.clone().map(|x| x as f32).$FUN(f32::atan2) }) }); } pub fn string_format(c: &mut Criterion) { // This goes quadratic with linear `fold1`, so use a smaller // size to not waste too much time in travis. The allocations // in here are so expensive anyway that it'll still take // way longer per iteration than the other two benchmarks. let v: Vec = (0.. ($N/4)).collect(); c.bench_function(&(stringify!($BENCH_NAME).replace('_', " ") + " string format"), move |b| { b.iter(|| { cloned(&v).map(|x| x.to_string()).$FUN(|x, y| format!("{} + {}", x, y)) }) }); } } criterion_group!( $BENCH_NAME, $BENCH_NAME::sum, $BENCH_NAME::complex_iter, $BENCH_NAME::string_format, ); ) } def_benchs!{ 10_000, fold1, fold1_10k, } def_benchs!{ 10_000, tree_fold1, tree_fold1_stack_10k, } def_benchs!{ 10_000, tree_fold1_vec, tree_fold1_vec_10k, } def_benchs!{ 100, fold1, fold1_100, } def_benchs!{ 100, tree_fold1, tree_fold1_stack_100, } def_benchs!{ 100, tree_fold1_vec, tree_fold1_vec_100, } def_benchs!{ 8, fold1, fold1_08, } def_benchs!{ 8, tree_fold1, tree_fold1_stack_08, } def_benchs!{ 8, tree_fold1_vec, tree_fold1_vec_08, } criterion_main!( fold1_10k, tree_fold1_stack_10k, tree_fold1_vec_10k, fold1_100, tree_fold1_stack_100, tree_fold1_vec_100, fold1_08, tree_fold1_stack_08, tree_fold1_vec_08, );