#! [cfg_attr(feature = "specialize" , feature(build_hasher_simple_hash_one))]
use ahash::{AHasher, RandomState};
use criterion::*;
use fxhash::FxHasher;
use rand::Rng;
use std::collections::hash_map::DefaultHasher;
use std::hash::{BuildHasherDefault, Hash, Hasher};
// Needs to be in sync with `src/lib.rs`
const AHASH_IMPL: &str = if cfg!(any(
all(
any(target_arch = "x86" , target_arch = "x86_64" ),
target_feature = "aes" ,
not(miri),
),
all(feature = "nightly-arm-aes" , target_arch = "aarch64" , target_feature = "aes" , not(miri)),
all(
feature = "nightly-arm-aes" ,
target_arch = "arm" ,
target_feature = "aes" ,
not(miri)
),
)) {
"aeshash"
} else {
"fallbackhash"
};
fn ahash<H: Hash>(b: &H) -> u64 {
let build_hasher = RandomState::with_seeds(1 , 2 , 3 , 4 );
build_hasher.hash_one(b)
}
fn fnvhash<H: Hash>(b: &H) -> u64 {
let mut hasher = fnv::FnvHasher::default();
b.hash(&mut hasher);
hasher.finish()
}
fn siphash<H: Hash>(b: &H) -> u64 {
let mut hasher = DefaultHasher::default();
b.hash(&mut hasher);
hasher.finish()
}
fn fxhash<H: Hash>(b: &H) -> u64 {
let mut hasher = FxHasher::default();
b.hash(&mut hasher);
hasher.finish()
}
fn seahash<H: Hash>(b: &H) -> u64 {
let mut hasher = seahash::SeaHasher::default();
b.hash(&mut hasher);
hasher.finish()
}
const STRING_LENGTHS: [u32; 12 ] = [1 , 3 , 4 , 7 , 8 , 15 , 16 , 24 , 33 , 68 , 132 , 1024 ];
fn gen_strings() -> Vec<String> {
STRING_LENGTHS
.iter()
.map(|len| {
let mut string = String::default();
for pos in 1 ..=*len {
let c = (48 + (pos % 10 ) as u8) as char;
string.push(c);
}
string
})
.collect()
}
macro_rules! bench_inputs {
($group:ident, $hash:ident) => {
// Number of iterations per batch should be high enough to hide timing overhead.
let size = BatchSize::NumIterations(50 _000 );
let mut rng = rand::thread_rng();
$group.bench_function("u8" , |b| b.iter_batched(|| rng.gen ::<u8>(), |v| $hash(&v), size));
$group.bench_function("u16" , |b| b.iter_batched(|| rng.gen ::<u16>(), |v| $hash(&v), size));
$group.bench_function("u32" , |b| b.iter_batched(|| rng.gen ::<u32>(), |v| $hash(&v), size));
$group.bench_function("u64" , |b| b.iter_batched(|| rng.gen ::<u64>(), |v| $hash(&v), size));
$group.bench_function("u128" , |b| b.iter_batched(|| rng.gen ::<u128>(), |v| $hash(&v), size));
$group.bench_with_input("strings" , &gen_strings(), |b, s| b.iter(|| $hash(black_box(s))));
};
}
fn bench_ahash(c: &mut Criterion) {
let mut group = c.benchmark_group(AHASH_IMPL);
bench_inputs!(group, ahash);
}
fn bench_fx(c: &mut Criterion) {
let mut group = c.benchmark_group("fx" );
bench_inputs!(group, fxhash);
}
fn bench_fnv(c: &mut Criterion) {
let mut group = c.benchmark_group("fnv" );
bench_inputs!(group, fnvhash);
}
fn bench_sea(c: &mut Criterion) {
let mut group = c.benchmark_group("sea" );
bench_inputs!(group, seahash);
}
fn bench_sip(c: &mut Criterion) {
let mut group = c.benchmark_group("sip" );
bench_inputs!(group, siphash);
}
fn bench_map(c: &mut Criterion) {
#[ cfg(feature = "std" )]
{
let mut group = c.benchmark_group("map" );
group.bench_function("aHash-alias" , |b| {
b.iter(|| {
let hm: ahash::HashMap<i32, i32> = (0 ..1 _000 _000 ).map(|i| (i, i)).collect();
let mut sum = 0 ;
for i in 0 ..1 _000 _000 {
if let Some(x) = hm.get(&i) {
sum += x;
}
}
})
});
group.bench_function("aHash-hashBrown" , |b| {
b.iter(|| {
let hm: hashbrown::HashMap<i32, i32> = (0 ..1 _000 _000 ).map(|i| (i, i)).collect();
let mut sum = 0 ;
for i in 0 ..1 _000 _000 {
if let Some(x) = hm.get(&i) {
sum += x;
}
}
})
});
group.bench_function("aHash-hashBrown-explicit" , |b| {
b.iter(|| {
let hm: hashbrown::HashMap<i32, i32, RandomState> = (0 ..1 _000 _000 ).map(|i| (i, i)).collect();
let mut sum = 0 ;
for i in 0 ..1 _000 _000 {
if let Some(x) = hm.get(&i) {
sum += x;
}
}
})
});
group.bench_function("aHash-wrapper" , |b| {
b.iter(|| {
let hm: ahash::AHashMap<i32, i32> = (0 ..1 _000 _000 ).map(|i| (i, i)).collect();
let mut sum = 0 ;
for i in 0 ..1 _000 _000 {
if let Some(x) = hm.get(&i) {
sum += x;
}
}
})
});
group.bench_function("aHash-rand" , |b| {
b.iter(|| {
let hm: std::collections::HashMap<i32, i32, RandomState> = (0 ..1 _000 _000 ).map(|i| (i, i)).collect();
let mut sum = 0 ;
for i in 0 ..1 _000 _000 {
if let Some(x) = hm.get(&i) {
sum += x;
}
}
})
});
group.bench_function("aHash-default" , |b| {
b.iter(|| {
let hm: std::collections::HashMap<i32, i32, BuildHasherDefault<AHasher>> =
(0 ..1 _000 _000 ).map(|i| (i, i)).collect();
let mut sum = 0 ;
for i in 0 ..1 _000 _000 {
if let Some(x) = hm.get(&i) {
sum += x;
}
}
})
});
}
}
criterion_main!(benches);
criterion_group!(
benches,
bench_ahash,
bench_fx,
bench_fnv,
bench_sea,
bench_sip,
bench_map
);
Messung V0.5 in Prozent C=81 H=91 G=85
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-18)
¤
*© Formatika GbR, Deutschland