use criterion::{Bencher, BenchmarkId, Criterion}; use std::mem; macro_rules! benches { ( $({ $len:expr, ($($member:ident),* $(,)?), insert = [$($insert:ident),* $(,)?], get => $get:ident, entry => [$($entry:ident),* $(,)?], };)* ) => { fn get_benches(criterion: &mut Criterion) { let mut group = criterion.benchmark_group("get"); $({ #[allow(unused)] #[derive(Clone, Copy, fixed_map::Key)] pub enum Key { $($member,)* } // Assert that size of Key is identical to array. const _: () = assert!( mem::size_of::<::MapStorage>() == mem::size_of::<[Option; $len]>() ); group.bench_with_input(BenchmarkId::new("fixed", $len), &$len, |b: &mut Bencher, _| { let mut it = 1u32..; let mut map = fixed_map::Map::new(); $(map.insert(Key::$insert, it.next().unwrap());)* b.iter(|| map.get(Key::$get)) }); })* $({ #[allow(unused)] #[derive(PartialEq, Eq, Hash)] pub enum Key { $($member,)* } group.bench_with_input(BenchmarkId::new("hashbrown", $len), &$len, |b: &mut Bencher, _| { let mut it = 1u32..; let mut map = hashbrown::HashMap::with_capacity($len); $(map.insert(Key::$insert, it.next().unwrap());)* b.iter(|| map.get(&Key::$get)) }); })* $({ #[allow(unused)] #[repr(usize)] pub enum Key { $($member,)* } group.bench_with_input(BenchmarkId::new("array", $len), &$len, |b: &mut Bencher, _| { let mut it = 1u32..; let mut map = [None; $len]; $(map[Key::$insert as usize] = Some(it.next().unwrap());)* b.iter(|| map[Key::$get as usize]) }); })* } fn insert_benches(criterion: &mut Criterion) { let mut group = criterion.benchmark_group("insert"); $({ #[allow(unused)] #[derive(Clone, Copy, fixed_map::Key)] pub enum Key { $($member,)* } group.bench_with_input(BenchmarkId::new("fixed", $len), &$len, |b: &mut Bencher, _| { b.iter(|| { let mut map = fixed_map::Map::::new(); $(map.insert(Key::$insert, 42u32);)* ($(map.get(Key::$insert).cloned(),)*) }) }); })* $({ #[allow(unused)] #[derive(Clone, PartialEq, Eq, Hash)] pub enum Key { $($member,)* } group.bench_with_input(BenchmarkId::new("hashbrown", $len), &$len, |b: &mut Bencher, _| { b.iter(|| { let mut map = hashbrown::HashMap::<_, u32>::with_capacity($len); $(map.insert(Key::$insert, 42u32);)* ($(map.get(&Key::$insert).cloned(),)*) }) }); })* $({ #[allow(unused)] #[repr(usize)] pub enum Key { $($member,)* } group.bench_with_input(BenchmarkId::new("array", $len), &$len, |b: &mut Bencher, _| { b.iter(|| { let mut map = [None; $len]; $(map[Key::$insert as usize] = Some(42u32);)* ($(map[Key::$insert as usize].as_ref().cloned(),)*) }) }); })* } fn values_benches(criterion: &mut Criterion) { let mut group = criterion.benchmark_group("values"); $({ #[allow(unused)] #[derive(Clone, Copy, fixed_map::Key)] pub enum Key { $($member,)* } group.bench_with_input(BenchmarkId::new("fixed", $len), &$len, |b: &mut Bencher, _| { let mut it = 1u32..; let mut map = fixed_map::Map::new(); $(map.insert(Key::$insert, it.next().unwrap());)* b.iter(|| map.values().copied().sum::()) }); })* $({ #[allow(unused)] #[derive(PartialEq, Eq, Hash)] pub enum Key { $($member,)* } group.bench_with_input(BenchmarkId::new("hashbrown", $len), &$len, |b: &mut Bencher, len| { let mut it = 1u32..; let mut map = hashbrown::HashMap::with_capacity(*len); $(map.insert(Key::$insert, it.next().unwrap());)* b.iter(|| map.values().copied().sum::()) }); })* $({ #[allow(unused)] #[repr(usize)] pub enum Key { $($member,)* } group.bench_with_input(BenchmarkId::new("array", $len), &$len, |b: &mut Bencher, _| { let mut it = 1u32..; let mut map = [None; $len]; $(map[Key::$insert as usize] = Some(it.next().unwrap());)* b.iter(|| map.iter().flatten().copied().sum::()) }); })* } fn entry_benches(criterion: &mut Criterion) { let mut group = criterion.benchmark_group("entry"); $({ #[allow(unused)] #[derive(Clone, Copy, fixed_map::Key)] pub enum Key { $($member,)* } group.bench_with_input(BenchmarkId::new("fixed", $len), &$len, |b: &mut Bencher, _| { let mut it = 1u32..; let mut map = fixed_map::Map::new(); $(map.insert(Key::$insert, it.next().unwrap());)* b.iter(|| { let mut value = 0; let mut map = map.clone(); $({ let v = map.entry(Key::$entry).or_default(); *v += 1; value += *v; })* value }); }); })* $({ #[allow(unused)] #[derive(Clone, PartialEq, Eq, Hash)] pub enum Key { $($member,)* } group.bench_with_input(BenchmarkId::new("hashbrown", $len), &$len, |b: &mut Bencher, _| { let mut it = 1u32..; let mut map = hashbrown::HashMap::with_capacity($len); $(map.insert(Key::$insert, it.next().unwrap());)* b.iter(|| { let mut map = map.clone(); let mut value = 0; $({ let v = map.entry(Key::$entry).or_default(); *v += 1; value += *v; })* value }); }); })* $({ #[allow(unused)] #[repr(usize)] pub enum Key { $($member,)* } group.bench_with_input(BenchmarkId::new("array", $len), &$len, |b: &mut Bencher, _| { let mut it = 1u32..; let mut map = [None; $len]; $(map[Key::$insert as usize] = Some(it.next().unwrap());)* b.iter(|| { let mut map = map; let mut value = 0; $({ let v = map[Key::$entry as usize].get_or_insert_with(Default::default); *v += 1; value += *v; })* value }); }); })* }} } benches! { { 4, (T00, T01, T02, T03), insert = [T00, T03], get => T03, entry => [T02, T03], }; { 8, (T00, T01, T02, T03, T04, T05, T06, T07), insert = [T00, T03, T06], get => T03, entry => [T02, T03], }; { 16, (T00, T01, T02, T03, T04, T05, T06, T07, T8, T9, T10, T11, T12, T13, T14, T15), insert = [T00, T03, T06, T12, T14], get => T14, entry => [T02, T14], }; { 32, ( T00, T01, T02, T03, T04, T05, T06, T07, T08, T09, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31 ), insert = [T00, T03, T06, T12, T14, T23, T28, T31], get => T28, entry => [T11, T28], }; } criterion::criterion_group! { name = complex; config = Criterion::default(); targets = get_benches, insert_benches, values_benches, entry_benches } criterion::criterion_main!(complex);