diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index a00fff2..2aa4d49 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -36,7 +36,7 @@ jobs: run: rustup default nightly - name: Benchmark - run: cargo bench --bench throughput --features bench-plot hybrid + run: cargo bench --bench throughput --features bench-plot,hybrid - uses: actions/upload-artifact@v3 with: diff --git a/benches/hashset.rs b/benches/hashset.rs index a247a3a..1a9f922 100644 --- a/benches/hashset.rs +++ b/benches/hashset.rs @@ -22,13 +22,18 @@ fn benchmark(c: &mut Criterion, name: &str, value: T) { let mut group = c.benchmark_group(format!("HashSet/{}", name)); + let mut set: HashSet:: = gxhash::HashSet::::default(); + group.bench_function("GxHash", |b| { + iterate(b, &value, &mut set); + }); + let mut set = HashSet::::new(); group.bench_function("Default Hasher", |b| { iterate(b, &value, &mut set); }); - let mut set: HashSet:: = gxhash::HashSet::::default(); - group.bench_function("GxHash", |b| { + let mut set = HashSet::>::default(); + group.bench_function("XxHash (XXH3)", |b| { iterate(b, &value, &mut set); }); @@ -37,8 +42,8 @@ fn benchmark(c: &mut Criterion, name: &str, value: T) iterate(b, &value, &mut set); }); - let mut set = HashSet::>::default(); - group.bench_function("XxHash", |b| { + let mut set = t1ha::T1haHashSet::::default(); + group.bench_function("T1ha", |b| { iterate(b, &value, &mut set); }); @@ -47,11 +52,6 @@ fn benchmark(c: &mut Criterion, name: &str, value: T) iterate(b, &value, &mut set); }); - let mut set = t1ha::T1haHashSet::::default(); - group.bench_function("T1ha", |b| { - iterate(b, &value, &mut set); - }); - let mut set = HashSet::::default(); group.bench_function("HighwayHash", |b| { iterate(b, &value, &mut set); diff --git a/benches/quality/main.rs b/benches/quality/main.rs index 1c75e86..e559451 100644 --- a/benches/quality/main.rs +++ b/benches/quality/main.rs @@ -4,10 +4,10 @@ use criterion::black_box; fn main() { bench_hasher_quality::("GxHash"); + bench_hasher_quality::("Default"); + bench_hasher_quality::("XxHash (XXH3)"); bench_hasher_quality::("AHash"); bench_hasher_quality::("T1ha"); - bench_hasher_quality::("XxHash3"); - bench_hasher_quality::("Default"); bench_hasher_quality::("FNV-1a"); } diff --git a/benches/throughput/aarch64.svg b/benches/throughput/aarch64.svg index 81629ea..bebea7a 100644 --- a/benches/throughput/aarch64.svg +++ b/benches/throughput/aarch64.svg @@ -4,13 +4,13 @@ Throughput (aarch64) - - - - - - - + + + + + + + Throughput (MiB/s) @@ -32,46 +32,46 @@ Input Size (bytes) - - - - - - - + + + + + + + 0 - + 5000 - - + + 10000 - - + + 15000 - - + + 20000 - - + + 25000 - - + + 30000 - - + + 35000 - + 4 @@ -129,46 +129,46 @@ Input Size (bytes) 32768 - - - - - - - - - - - -gxhash - - -xxhash - - -ahash - - -t1ha0 - - -seahash - - -metrohash - - -highwayhash - - -fnv-1a - - - - - - - - - + + + + + + + + + + + +GxHash + + +XxHash (XXH3) + + +AHash + + +T1ha0 + + +FNV-1a + + +HighwayHash + + +SeaHash + + +Metrohash + + + + + + + + + diff --git a/benches/throughput/main.rs b/benches/throughput/main.rs index 3a48963..c84a9cc 100644 --- a/benches/throughput/main.rs +++ b/benches/throughput/main.rs @@ -38,52 +38,52 @@ fn main() { }; // GxHash - let gxhash_name = if cfg!(hybrid) { "gxhash-hybrid" } else { "gxhash" }; + let gxhash_name = if cfg!(feature = "hybrid") { "GxHash-Hybrid" } else { "GxHash" }; benchmark(processor.as_mut(), slice, gxhash_name, |data: &[u8], seed: i64| -> u64 { gxhash64(data, seed) }); // XxHash (twox-hash) - benchmark(processor.as_mut(), slice, "xxhash", |data: &[u8], seed: u64| -> u64 { + benchmark(processor.as_mut(), slice, "XxHash (XXH3)", |data: &[u8], seed: u64| -> u64 { twox_hash::xxh3::hash64_with_seed(data, seed) }); // AHash let ahash_hasher = ahash::RandomState::with_seeds(0, 0, 0, 0); - benchmark(processor.as_mut(), slice, "ahash", |data: &[u8], _: i32| -> u64 { + benchmark(processor.as_mut(), slice, "AHash", |data: &[u8], _: i32| -> u64 { ahash_hasher.hash_one(data) }); // T1ha0 - benchmark(processor.as_mut(), slice, "t1ha0", |data: &[u8], seed: u64| -> u64 { + benchmark(processor.as_mut(), slice, "T1ha0", |data: &[u8], seed: u64| -> u64 { t1ha::t1ha0(data, seed) }); + // FNV-1a + benchmark(processor.as_mut(), slice, "FNV-1a", |data: &[u8], seed: u64| -> u64 { + let mut fnv_hasher = fnv::FnvHasher::with_key(seed); + fnv_hasher.write(data); + fnv_hasher.finish() + }); + + // HighwayHash + benchmark(processor.as_mut(), slice, "HighwayHash", |data: &[u8], _: i32| -> u64 { + use highway::{HighwayHasher, HighwayHash}; + HighwayHasher::default().hash64(data) + }); + // SeaHash - benchmark(processor.as_mut(), slice, "seahash", |data: &[u8], seed: u64| -> u64 { + benchmark(processor.as_mut(), slice, "SeaHash", |data: &[u8], seed: u64| -> u64 { seahash::hash_seeded(data, seed, 0, 0, 0) }); // MetroHash - benchmark(processor.as_mut(), slice, "metrohash", |data: &[u8], seed: i32| -> u64 { + benchmark(processor.as_mut(), slice, "Metrohash", |data: &[u8], seed: i32| -> u64 { let mut metrohash_hasher = metrohash::MetroHash64::with_seed(seed as u64); metrohash_hasher.write(data); metrohash_hasher.finish() }); - // HighwayHash - benchmark(processor.as_mut(), slice, "highwayhash", |data: &[u8], _: i32| -> u64 { - use highway::{HighwayHasher, HighwayHash}; - HighwayHasher::default().hash64(data) - }); - - // FNV-1a - benchmark(processor.as_mut(), slice, "fnv-1a", |data: &[u8], seed: u64| -> u64 { - let mut fnv_hasher = fnv::FnvHasher::with_key(seed); - fnv_hasher.write(data); - fnv_hasher.finish() - }); - processor.finish(); // Free benchmark data diff --git a/benches/throughput/result_processor.rs b/benches/throughput/result_processor.rs index 2b15546..c7dbbeb 100644 --- a/benches/throughput/result_processor.rs +++ b/benches/throughput/result_processor.rs @@ -120,7 +120,8 @@ impl ResultProcessor for OutputPlot { fn finish(&self) { let mut arch = std::env::consts::ARCH.to_string(); - if cfg!(hybrid) { + if cfg!(feature = "hybrid") { + println!("Hybrid feature enabled"); arch += "-hybrid"; } let file_name = format!("benches/throughput/{}.svg", arch); diff --git a/benches/throughput/x86_64-hybrid.svg b/benches/throughput/x86_64-hybrid.svg index 1ded506..ea05a09 100644 --- a/benches/throughput/x86_64-hybrid.svg +++ b/benches/throughput/x86_64-hybrid.svg @@ -4,13 +4,14 @@ Throughput (x86_64-hybrid) - - - - - - - + + + + + + + + Throughput (MiB/s) @@ -32,46 +33,51 @@ Input Size (bytes) - - - - - - - + + + + + + + + 0 - + 20000 - - + + 40000 - - + + 60000 - - + + 80000 - - + + 100000 - - + + 120000 - - + + 140000 - + + +160000 + + 4 @@ -129,39 +135,39 @@ Input Size (bytes) 32768 - - - - - - - - + + + + + + + + -gxhash-hybrid +GxHash-Hybrid -xxhash +XxHash (XXH3) -ahash +AHash -t1ha0 +T1ha0 -seahash +FNV-1a -metrohash +HighwayHash -highwayhash +SeaHash -fnv-1a +Metrohash diff --git a/benches/throughput/x86_64.svg b/benches/throughput/x86_64.svg index 1c31513..e306731 100644 --- a/benches/throughput/x86_64.svg +++ b/benches/throughput/x86_64.svg @@ -4,12 +4,11 @@ Throughput (x86_64) - - - - - - + + + + + Throughput (MiB/s) @@ -31,41 +30,36 @@ Input Size (bytes) - - - - - - + + + + + 0 - + 20000 - - + + 40000 - - + + 60000 - - + + 80000 - - + + 100000 - - -120000 - - + 4 @@ -123,46 +117,46 @@ Input Size (bytes) 32768 - - - - - - - - - - - -gxhash - - -xxhash - - -ahash - - -t1ha0 - - -seahash - - -metrohash - - -highwayhash - - -fnv-1a - - - - - - - - - + + + + + + + + + + + +GxHash + + +XxHash (XXH3) + + +AHash + + +T1ha0 + + +FNV-1a + + +HighwayHash + + +SeaHash + + +Metrohash + + + + + + + + + diff --git a/benches/throughput_criterion.rs b/benches/throughput_criterion.rs index 7d355fa..5fb7ce7 100644 --- a/benches/throughput_criterion.rs +++ b/benches/throughput_criterion.rs @@ -44,40 +44,40 @@ fn benchmark_all(c: &mut Criterion) { group.plot_config(plot_config); // GxHash - let gxhash_name = if cfg!(hybrid) { "gxhash-hybrid" } else { "gxhash" }; + let gxhash_name = if cfg!(feature = "hybrid") { "GxHash-Hybrid" } else { "GxHash" }; benchmark(&mut group, slice, gxhash_name, |data: &[u8], seed: i32| -> u64 { gxhash64(data, seed as i64) }); - + + // XxHash (twox-hash) + benchmark(&mut group, slice, "XxHash (XXH3)", |data: &[u8], seed: i32| -> u64 { + twox_hash::xxh3::hash64_with_seed(data, seed as u64) + }); + // AHash - benchmark(&mut group, slice, "ahash", |data: &[u8], seed: i32| -> u64 { + benchmark(&mut group, slice, "AHash", |data: &[u8], seed: i32| -> u64 { let ahash_hasher = ahash::RandomState::with_seeds(seed as u64, 0, 0, 0); ahash_hasher.hash_one(data) }); // T1ha0 - benchmark(&mut group, slice, "t1ha0", |data: &[u8], seed: i32| -> u64 { + benchmark(&mut group, slice, "T1ha0", |data: &[u8], seed: i32| -> u64 { t1ha::t1ha0(data, seed as u64) }); - // XxHash (twox-hash) - benchmark(&mut group, slice, "xxhash", |data: &[u8], seed: i32| -> u64 { - twox_hash::xxh3::hash64_with_seed(data, seed as u64) + // FNV-1a + benchmark(&mut group, slice, "FNV-1a", |data: &[u8], seed: i32| -> u64 { + let mut fnv_hasher = fnv::FnvHasher::with_key(seed as u64); + fnv_hasher.write(data); + fnv_hasher.finish() }); // HighwayHash - benchmark(&mut group, slice, "highwayhash", |data: &[u8], _: i32| -> u64 { + benchmark(&mut group, slice, "HighwayHash", |data: &[u8], _: i32| -> u64 { use highway::{HighwayHasher, HighwayHash}; HighwayHasher::default().hash64(data) }); - // FNV-1a - benchmark(&mut group, slice, "fnv-1a", |data: &[u8], seed: i32| -> u64 { - let mut fnv_hasher = fnv::FnvHasher::with_key(seed as u64); - fnv_hasher.write(data); - fnv_hasher.finish() - }); - group.finish(); // Free benchmark data diff --git a/src/gxhash/platform/arm.rs b/src/gxhash/platform/arm.rs index 083e6e8..fc40b92 100644 --- a/src/gxhash/platform/arm.rs +++ b/src/gxhash/platform/arm.rs @@ -25,7 +25,7 @@ pub unsafe fn load_unaligned(p: *const State) -> State { vld1q_s8(p as *const i8) } -#[inline(never)] +#[inline(always)] pub unsafe fn get_partial_safe(data: *const State, len: usize) -> State { // Temporary buffer filled with zeros let mut buffer = [0i8; VECTOR_SIZE];