mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-23 14:52:24 +00:00
145 lines
3.4 KiB
Rust
145 lines
3.4 KiB
Rust
|
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<F>(self, mut f: F) -> Option<Self::Item>
|
||
|
where F: FnMut(Self::Item, Self::Item) -> Self::Item,
|
||
|
Self: Sized,
|
||
|
{
|
||
|
let hint = self.size_hint().0;
|
||
|
let cap = std::mem::size_of::<usize>() * 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<T:Iterator> 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<u32> = (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<u32> = (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,
|
||
|
);
|