use criterion::{criterion_group, criterion_main, Bencher, Criterion}; use dynstack::{dyn_push, DynStack}; use std::fmt::Display; trait ATrait {} struct Large([u8; 950]); impl Large { pub fn new() -> Self { Self([3; 950]) } } impl ATrait for Large {} fn new_speed_naive(b: &mut Bencher) { b.iter(Vec::>::new); } fn new_speed_dynstack(b: &mut Bencher) { b.iter(DynStack::::new); } fn push_large_speed_naive(b: &mut Bencher) { b.iter(|| { let mut vec = Vec::>::new(); vec.push(Box::new(Large::new())); vec }); } fn push_large_speed_dynstack(b: &mut Bencher) { b.iter(|| { let mut stack = DynStack::::new(); dyn_push!(stack, Large::new()); stack }); } fn push_speed_naive(b: &mut Bencher) { let mut vec = Vec::>::new(); b.iter(|| { vec.push(Box::new(0xF00BAAusize)); vec.push(Box::new(0xABBAu16)); vec.push(Box::new(0xBA7123AAu32)); vec.push(Box::new(12u8)); }); } fn push_speed_dynstack(b: &mut Bencher) { let mut stack = DynStack::::new(); b.iter(|| { dyn_push!(stack, 0xF00BAAusize); dyn_push!(stack, 0xABBAu16); dyn_push!(stack, 0xBA7123AAu32); dyn_push!(stack, 12u8); }); } fn push_and_run_naive(b: &mut Bencher) { b.iter(|| { let mut stack = Vec:: usize>>::new(); fn pseudorecursive(stack: &mut Vec usize>>, n: usize) { stack.push(Box::new(move || n - 1)); } let mut n = 100; let mut i = 0; while n > 0 { pseudorecursive(&mut stack, n); n = (stack.get(i).unwrap())(); i += 1; } }); } fn push_and_run_dynstack(b: &mut Bencher) { b.iter(|| { let mut stack = DynStack:: usize>::new(); fn pseudorecursive(stack: &mut DynStack usize>, n: usize) { dyn_push!(stack, move || n - 1); } let mut n = 100; let mut i = 0; while n > 0 { pseudorecursive(&mut stack, n); n = (stack.get(i).unwrap())(); i += 1; } }); } fn pseudorecursive2_naive(b: &mut Bencher) { b.iter(|| { let mut state: Box usize> = Box::new(|| 0); fn pseudorecursive(state: &mut Box usize>, n: usize) { *state = Box::new(move || n - 1); } let mut n = 100; while n > 0 { pseudorecursive(&mut state, n); n = state(); } }); } fn pseudorecursive2_dynstack(b: &mut Bencher) { b.iter(|| { let mut stack = DynStack:: usize>::new(); fn pseudorecursive(stack: &mut DynStack usize>, n: usize) { dyn_push!(stack, move || n - 1); } let mut n = 100; while n > 0 { pseudorecursive(&mut stack, n); n = (stack.peek().unwrap())(); stack.remove_last(); } }); } trait AsUsize { fn make(&self) -> usize; } impl AsUsize for usize { fn make(&self) -> usize { *self } } fn access_naive(b: &mut Bencher) { let mut stack = Vec::>::new(); for _ in 0..1000 { stack.push(Box::new(0xF00BAAusize)); } b.iter(|| { for i in &stack { criterion::black_box(i.make()); } }); } fn access_dynstack(b: &mut Bencher) { let mut stack = DynStack::::new(); for _ in 0..1000 { dyn_push!(stack, 0xF00BAAusize); } b.iter(|| { for i in &stack { criterion::black_box(i.make()); } }); } fn criterion_benchmark(c: &mut Criterion) { c.bench_function("new_speed_naive", new_speed_naive); c.bench_function("new_speed_dynstack", new_speed_dynstack); c.bench_function("push_large_speed_naive", push_large_speed_naive); c.bench_function("push_large_speed_dynstack", push_large_speed_dynstack); c.bench_function("push_speed_naive", push_speed_naive); c.bench_function("push_speed_dynstack", push_speed_dynstack); c.bench_function("push_and_run_naive", push_and_run_naive); c.bench_function("push_and_run_dynstack", push_and_run_dynstack); c.bench_function("pseudorecursive2_naive", pseudorecursive2_naive); c.bench_function("pseudorecursive2_dynstack", pseudorecursive2_dynstack); c.bench_function("access_naive", access_naive); c.bench_function("access_dynstack", access_dynstack); } criterion_group!(benches, criterion_benchmark); criterion_main!(benches);