#![allow(deprecated)] use criterion::{criterion_group, criterion_main, Criterion}; use itertools::{cloned, Itertools}; trait IterEx: Iterator { // Another efficient implementation against which to compare, // but needs `std` so is less desirable. fn tree_reduce_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_reduce, tree_reduce_stack_10k, } def_benchs! { 10_000, tree_reduce_vec, tree_reduce_vec_10k, } def_benchs! { 100, fold1, fold1_100, } def_benchs! { 100, tree_reduce, tree_reduce_stack_100, } def_benchs! { 100, tree_reduce_vec, tree_reduce_vec_100, } def_benchs! { 8, fold1, fold1_08, } def_benchs! { 8, tree_reduce, tree_reduce_stack_08, } def_benchs! { 8, tree_reduce_vec, tree_reduce_vec_08, } criterion_main!( fold1_10k, tree_reduce_stack_10k, tree_reduce_vec_10k, fold1_100, tree_reduce_stack_100, tree_reduce_vec_100, fold1_08, tree_reduce_stack_08, tree_reduce_vec_08, );