diff --git a/Cargo.toml b/Cargo.toml index f0f665b5b4..fd7170f175 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ serde_test = "1.0" doc-comment = "0.3.1" bumpalo = { version = "3.13.0", features = ["allocator-api2"] } rkyv = { version = "0.7.42", features = ["validation"] } +gxhash = "3.0.0" [features] default = ["ahash", "inline-more", "allocator-api2"] diff --git a/benches/bench.rs b/benches/bench.rs index 346bd7ef89..a92aa31559 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -22,6 +22,8 @@ type AHashMap = HashMap; // This uses the hashmap from this crate with the default hasher of the stdlib. type StdHashMap = HashMap; +type GxHashMap = HashMap; + // A random key iterator. #[derive(Clone, Copy)] struct RandomKeys { @@ -58,11 +60,17 @@ impl Drop for DropType { } macro_rules! bench_suite { - ($bench_macro:ident, $bench_ahash_serial:ident, $bench_std_serial:ident, - $bench_ahash_highbits:ident, $bench_std_highbits:ident, - $bench_ahash_random:ident, $bench_std_random:ident) => { + ($bench_macro:ident, $bench_gxhash_serial:ident, $bench_ahash_serial:ident, $bench_std_serial:ident, + $bench_gxhash_highbits:ident, $bench_ahash_highbits:ident, $bench_std_highbits:ident, + $bench_gxhash_random:ident, $bench_ahash_random:ident, $bench_std_random:ident) => { + $bench_macro!($bench_gxhash_serial, GxHashMap, 0..); $bench_macro!($bench_ahash_serial, AHashMap, 0..); $bench_macro!($bench_std_serial, StdHashMap, 0..); + $bench_macro!( + $bench_gxhash_highbits, + GxHashMap, + (0..).map(usize::swap_bytes) + ); $bench_macro!( $bench_ahash_highbits, AHashMap, @@ -73,98 +81,108 @@ macro_rules! bench_suite { StdHashMap, (0..).map(usize::swap_bytes) ); + $bench_macro!($bench_gxhash_random, GxHashMap, RandomKeys::new()); $bench_macro!($bench_ahash_random, AHashMap, RandomKeys::new()); $bench_macro!($bench_std_random, StdHashMap, RandomKeys::new()); }; } -macro_rules! bench_insert { - ($name:ident, $maptype:ident, $keydist:expr) => { - #[bench] - fn $name(b: &mut Bencher) { - let mut m = $maptype::with_capacity_and_hasher(SIZE, Default::default()); - b.iter(|| { - m.clear(); - for i in ($keydist).take(SIZE) { - m.insert(i, (DropType(i), [i; 20])); - } - black_box(&mut m); - }); - eprintln!("{}", SIDE_EFFECT.load(atomic::Ordering::SeqCst)); - } - }; -} - -bench_suite!( - bench_insert, - insert_ahash_serial, - insert_std_serial, - insert_ahash_highbits, - insert_std_highbits, - insert_ahash_random, - insert_std_random -); - -macro_rules! bench_grow_insert { - ($name:ident, $maptype:ident, $keydist:expr) => { - #[bench] - fn $name(b: &mut Bencher) { - b.iter(|| { - let mut m = $maptype::default(); - for i in ($keydist).take(SIZE) { - m.insert(i, DropType(i)); - } - black_box(&mut m); - }) - } - }; -} - -bench_suite!( - bench_grow_insert, - grow_insert_ahash_serial, - grow_insert_std_serial, - grow_insert_ahash_highbits, - grow_insert_std_highbits, - grow_insert_ahash_random, - grow_insert_std_random -); - -macro_rules! bench_insert_erase { - ($name:ident, $maptype:ident, $keydist:expr) => { - #[bench] - fn $name(b: &mut Bencher) { - let mut base = $maptype::default(); - for i in ($keydist).take(SIZE) { - base.insert(i, DropType(i)); - } - let skip = $keydist.skip(SIZE); - b.iter(|| { - let mut m = base.clone(); - let mut add_iter = skip.clone(); - let mut remove_iter = $keydist; - // While keeping the size constant, - // replace the first keydist with the second. - for (add, remove) in (&mut add_iter).zip(&mut remove_iter).take(SIZE) { - m.insert(add, DropType(add)); - black_box(m.remove(&remove)); - } - black_box(m); - }); - eprintln!("{}", SIDE_EFFECT.load(atomic::Ordering::SeqCst)); - } - }; -} - -bench_suite!( - bench_insert_erase, - insert_erase_ahash_serial, - insert_erase_std_serial, - insert_erase_ahash_highbits, - insert_erase_std_highbits, - insert_erase_ahash_random, - insert_erase_std_random -); +// macro_rules! bench_insert { +// ($name:ident, $maptype:ident, $keydist:expr) => { +// #[bench] +// fn $name(b: &mut Bencher) { +// let mut m = $maptype::with_capacity_and_hasher(SIZE, Default::default()); +// b.iter(|| { +// m.clear(); +// for i in ($keydist).take(SIZE) { +// m.insert(i, (DropType(i), [i; 20])); +// } +// black_box(&mut m); +// }); +// eprintln!("{}", SIDE_EFFECT.load(atomic::Ordering::SeqCst)); +// } +// }; +// } + +// bench_suite!( +// bench_insert, +// insert_gxhash_serial, +// insert_ahash_serial, +// insert_std_serial, +// insert_gxhash_highbits, +// insert_ahash_highbits, +// insert_std_highbits, +// insert_gxhash_random, +// insert_ahash_random, +// insert_std_random +// ); + +// macro_rules! bench_grow_insert { +// ($name:ident, $maptype:ident, $keydist:expr) => { +// #[bench] +// fn $name(b: &mut Bencher) { +// b.iter(|| { +// let mut m = $maptype::default(); +// for i in ($keydist).take(SIZE) { +// m.insert(i, DropType(i)); +// } +// black_box(&mut m); +// }) +// } +// }; +// } + +// bench_suite!( +// bench_grow_insert, +// grow_insert_gxhash_serial, +// grow_insert_ahash_serial, +// grow_insert_std_serial, +// grow_insert_gxhash_highbits, +// grow_insert_ahash_highbits, +// grow_insert_std_highbits, +// grow_insert_gxhash_random, +// grow_insert_ahash_random, +// grow_insert_std_random +// ); + +// macro_rules! bench_insert_erase { +// ($name:ident, $maptype:ident, $keydist:expr) => { +// #[bench] +// fn $name(b: &mut Bencher) { +// let mut base = $maptype::default(); +// for i in ($keydist).take(SIZE) { +// base.insert(i, DropType(i)); +// } +// let skip = $keydist.skip(SIZE); +// b.iter(|| { +// let mut m = base.clone(); +// let mut add_iter = skip.clone(); +// let mut remove_iter = $keydist; +// // While keeping the size constant, +// // replace the first keydist with the second. +// for (add, remove) in (&mut add_iter).zip(&mut remove_iter).take(SIZE) { +// m.insert(add, DropType(add)); +// black_box(m.remove(&remove)); +// } +// black_box(m); +// }); +// eprintln!("{}", SIDE_EFFECT.load(atomic::Ordering::SeqCst)); +// } +// }; +// } + +// bench_suite!( +// bench_insert_erase, +// insert_erase_gxhash_serial, +// insert_erase_ahash_serial, +// insert_erase_std_serial, +// insert_erase_gxhash_highbits, +// insert_erase_ahash_highbits, +// insert_erase_std_highbits, +// insert_erase_gxhash_random, +// insert_erase_ahash_random, +// insert_erase_std_random +// ); macro_rules! bench_lookup { ($name:ident, $maptype:ident, $keydist:expr) => { @@ -177,7 +195,7 @@ macro_rules! bench_lookup { b.iter(|| { for i in $keydist.take(SIZE) { - black_box(m.get(&i)); + black_box(m.get(black_box(&i))); } }); eprintln!("{}", SIDE_EFFECT.load(atomic::Ordering::SeqCst)); @@ -187,70 +205,79 @@ macro_rules! bench_lookup { bench_suite!( bench_lookup, + lookup_gxhash_serial, lookup_ahash_serial, lookup_std_serial, + lookup_gxhash_highbits, lookup_ahash_highbits, lookup_std_highbits, + lookup_gxhash_random, lookup_ahash_random, lookup_std_random ); -macro_rules! bench_lookup_fail { - ($name:ident, $maptype:ident, $keydist:expr) => { - #[bench] - fn $name(b: &mut Bencher) { - let mut m = $maptype::default(); - let mut iter = $keydist; - for i in (&mut iter).take(SIZE) { - m.insert(i, DropType(i)); - } - - b.iter(|| { - for i in (&mut iter).take(SIZE) { - black_box(m.get(&i)); - } - }) - } - }; -} - -bench_suite!( - bench_lookup_fail, - lookup_fail_ahash_serial, - lookup_fail_std_serial, - lookup_fail_ahash_highbits, - lookup_fail_std_highbits, - lookup_fail_ahash_random, - lookup_fail_std_random -); - -macro_rules! bench_iter { - ($name:ident, $maptype:ident, $keydist:expr) => { - #[bench] - fn $name(b: &mut Bencher) { - let mut m = $maptype::default(); - for i in ($keydist).take(SIZE) { - m.insert(i, DropType(i)); - } - - b.iter(|| { - for i in &m { - black_box(i); - } - }) - } - }; -} - -bench_suite!( - bench_iter, - iter_ahash_serial, - iter_std_serial, - iter_ahash_highbits, - iter_std_highbits, - iter_ahash_random, - iter_std_random -); +// macro_rules! bench_lookup_fail { +// ($name:ident, $maptype:ident, $keydist:expr) => { +// #[bench] +// fn $name(b: &mut Bencher) { +// let mut m = $maptype::default(); +// let mut iter = $keydist; +// for i in (&mut iter).take(SIZE) { +// m.insert(i, DropType(i)); +// } + +// b.iter(|| { +// for i in (&mut iter).take(SIZE) { +// black_box(m.get(&i)); +// } +// }) +// } +// }; +// } + +// bench_suite!( +// bench_lookup_fail, +// lookup_fail_gxhash_serial, +// lookup_fail_ahash_serial, +// lookup_fail_std_serial, +// lookup_fail_gxhash_highbits, +// lookup_fail_ahash_highbits, +// lookup_fail_std_highbits, +// lookup_fail_gxhash_random, +// lookup_fail_ahash_random, +// lookup_fail_std_random +// ); + +// macro_rules! bench_iter { +// ($name:ident, $maptype:ident, $keydist:expr) => { +// #[bench] +// fn $name(b: &mut Bencher) { +// let mut m = $maptype::default(); +// for i in ($keydist).take(SIZE) { +// m.insert(i, DropType(i)); +// } + +// b.iter(|| { +// for i in &m { +// black_box(i); +// } +// }) +// } +// }; +// } + +// bench_suite!( +// bench_iter, +// iter_gxhash_serial, +// iter_ahash_serial, +// iter_std_serial, +// iter_gxhash_highbits, +// iter_ahash_highbits, +// iter_std_highbits, +// iter_gxhash_random, +// iter_ahash_random, +// iter_std_random +// ); #[bench] fn clone_small(b: &mut Bencher) {