1 // This benchmark suite contains some benchmarks along a set of dimensions:
2 // Hasher: std default (SipHash) and crate default (FxHash).
3 // Int key distribution: low bit heavy, top bit heavy, and random.
4 // Task: basic functionality: insert, insert_erase, lookup, lookup_fail, iter
9 use test
::{black_box, Bencher}
;
11 use hashbrown
::hash_map
::DefaultHashBuilder
;
12 use hashbrown
::HashMap
;
13 use std
::collections
::hash_map
::RandomState
;
15 const SIZE
: usize = 1000;
17 // The default hashmap when using this crate directly.
18 type FxHashMap
<K
, V
> = HashMap
<K
, V
, DefaultHashBuilder
>;
19 // This uses the hashmap from this crate with the default hasher of the stdlib.
20 type StdHashMap
<K
, V
> = HashMap
<K
, V
, RandomState
>;
22 // A random key iterator.
23 #[derive(Clone, Copy)]
30 RandomKeys { state: 0 }
34 impl Iterator
for RandomKeys
{
36 fn next(&mut self) -> Option
<usize> {
37 // Add 1 then multiply by some 32 bit prime.
38 self.state
= self.state
.wrapping_add(1).wrapping_mul(3787392781);
43 macro_rules
! bench_suite
{
44 ($bench_macro
:ident
, $bench_fx_serial
:ident
, $bench_std_serial
:ident
,
45 $bench_fx_highbits
:ident
, $bench_std_highbits
:ident
,
46 $bench_fx_random
:ident
, $bench_std_random
:ident
) => {
47 $bench_macro
!($bench_fx_serial
, FxHashMap
, 0..);
48 $bench_macro
!($bench_std_serial
, StdHashMap
, 0..);
49 $bench_macro
!($bench_fx_highbits
, FxHashMap
, (0..).map(usize::swap_bytes
));
53 (0..).map(usize::swap_bytes
)
55 $bench_macro
!($bench_fx_random
, FxHashMap
, RandomKeys
::new());
56 $bench_macro
!($bench_std_random
, StdHashMap
, RandomKeys
::new());
60 macro_rules
! bench_insert
{
61 ($name
:ident
, $maptype
:ident
, $keydist
:expr
) => {
63 fn $
name(b
: &mut Bencher
) {
65 let mut m
= $maptype
::default();
66 for i
in ($keydist
).take(SIZE
) {
85 macro_rules
! bench_insert_erase
{
86 ($name
:ident
, $maptype
:ident
, $keydist
:expr
) => {
88 fn $
name(b
: &mut Bencher
) {
89 let mut m
= $maptype
::default();
90 let mut add_iter
= $keydist
;
91 for i
in (&mut add_iter
).take(SIZE
) {
94 let mut remove_iter
= $keydist
;
96 // While keeping the size constant,
97 // replace the first keydist with the second.
98 for (add
, remove
) in (&mut add_iter
).zip(&mut remove_iter
).take(SIZE
) {
100 black_box(m
.remove(&remove
));
109 insert_erase_fx_serial
,
110 insert_erase_std_serial
,
111 insert_erase_fx_highbits
,
112 insert_erase_std_highbits
,
113 insert_erase_fx_random
,
114 insert_erase_std_random
117 macro_rules
! bench_lookup
{
118 ($name
:ident
, $maptype
:ident
, $keydist
:expr
) => {
120 fn $
name(b
: &mut Bencher
) {
121 let mut m
= $maptype
::default();
122 for i
in $keydist
.take(SIZE
) {
127 for i
in $keydist
.take(SIZE
) {
128 black_box(m
.get(&i
));
145 macro_rules
! bench_lookup_fail
{
146 ($name
:ident
, $maptype
:ident
, $keydist
:expr
) => {
148 fn $
name(b
: &mut Bencher
) {
149 let mut m
= $maptype
::default();
150 let mut iter
= $keydist
;
151 for i
in (&mut iter
).take(SIZE
) {
156 for i
in (&mut iter
).take(SIZE
) {
157 black_box(m
.get(&i
));
166 lookup_fail_fx_serial
,
167 lookup_fail_std_serial
,
168 lookup_fail_fx_highbits
,
169 lookup_fail_std_highbits
,
170 lookup_fail_fx_random
,
171 lookup_fail_std_random
174 macro_rules
! bench_iter
{
175 ($name
:ident
, $maptype
:ident
, $keydist
:expr
) => {
177 fn $
name(b
: &mut Bencher
) {
178 let mut m
= $maptype
::default();
179 for i
in ($keydist
).take(SIZE
) {