diff options
author | Matthew Maurer <mmaurer@google.com> | 2021-06-21 19:27:23 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2021-06-21 19:27:23 +0000 |
commit | d1ae879299bdef5050eabdc8b4b94d8b29bbfd0c (patch) | |
tree | c1f7becfd9e3155439a18e172cafcd947c2f03b2 | |
parent | d7a24759e145de26d2f9085c38352622616565df (diff) | |
parent | 456d737f1ebda04c56c1eab1be3ffb7771bfbc3a (diff) | |
download | ahash-d1ae879299bdef5050eabdc8b4b94d8b29bbfd0c.tar.gz |
Merge "Upgrade rust/crates/ahash to 0.7.4"
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | .github/workflows/rust.yml | 10 | ||||
-rw-r--r-- | Android.bp | 6 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | Cargo.toml.orig | 2 | ||||
-rw-r--r-- | METADATA | 8 | ||||
-rw-r--r-- | README.md | 16 | ||||
-rw-r--r-- | src/aes_hash.rs | 7 | ||||
-rw-r--r-- | src/fallback_hash.rs | 11 | ||||
-rw-r--r-- | src/hash_quality_test.rs | 45 | ||||
-rw-r--r-- | src/operations.rs | 1 | ||||
-rw-r--r-- | tests/bench.rs | 176 |
12 files changed, 114 insertions, 172 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index 3536048..a2c6e68 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,5 @@ { "git": { - "sha1": "4e3d12e517e0189a9e23df06d5eaacfc094510a4" + "sha1": "ffa04fcb81f39755f636c75c9b7aa06533c0ae75" } } diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b391d97..ba596bf 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -93,10 +93,16 @@ jobs: with: toolchain: stable target: i686-unknown-linux-gnu + - name: Install cross compile tools + run: sudo apt-get install -y gcc-multilib libc6-i386 libc6-dev-i386 - uses: actions-rs/cargo@v1 with: command: check args: --target i686-unknown-linux-gnu + - uses: actions-rs/cargo@v1 + with: + command: test + args: --target i686-unknown-linux-gnu x86_64-unknown-linux-gnu: name: Linux x86_64 - nightly runs-on: ubuntu-latest @@ -113,6 +119,10 @@ jobs: with: command: check args: --target x86_64-unknown-linux-gnu + - uses: actions-rs/cargo@v1 + with: + command: test + args: --target x86_64-unknown-linux-gnu thumbv6m: name: thumbv6m runs-on: ubuntu-latest @@ -66,7 +66,7 @@ rust_library { // dependent_library ["feature_list"] // cfg-if-1.0.0 -// getrandom-0.2.2 -// libc-0.2.94 "default,std" -// once_cell-1.7.2 "alloc,race,unstable" +// getrandom-0.2.3 +// libc-0.2.97 "default,std" +// once_cell-1.8.0 "alloc,race,unstable" // version_check-0.9.3 @@ -13,7 +13,7 @@ [package] edition = "2018" name = "ahash" -version = "0.7.2" +version = "0.7.4" authors = ["Tom Kaitchuck <Tom.Kaitchuck@gmail.com>"] build = "./build.rs" exclude = ["/smhasher"] diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 55c8f23..1b3e831 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "ahash" -version = "0.7.2" +version = "0.7.4" authors = ["Tom Kaitchuck <Tom.Kaitchuck@gmail.com>"] license = "MIT OR Apache-2.0" description = "A non-cryptographic hash function using AES-NI for high performance" @@ -7,13 +7,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/ahash/ahash-0.7.2.crate" + value: "https://static.crates.io/crates/ahash/ahash-0.7.4.crate" } - version: "0.7.2" + version: "0.7.4" license_type: NOTICE last_upgrade_date { year: 2021 - month: 5 - day: 19 + month: 6 + day: 14 } } @@ -19,17 +19,17 @@ AHash does *not* have a fixed standard for its output. This allows it to improve if any faster algorithm is found, aHash will be updated to incorporate the technique. Similarly, should any flaw in aHash's DOS resistance be found, aHash will be changed to correct the flaw. -Because it does not have a fixed standard, different computers or computers on versions of the code will observe different hash values. -As such aHash not recommended for use other than in-memory maps. Specifically, aHash is not intended for network use or in applications which persist hashed values. +Because it does not have a fixed standard, different computers or computers on different versions of the code will observe different hash values. +As such, aHash is not recommended for use other than in-memory maps. Specifically, aHash is not intended for network use or in applications which persist hashed values. (In these cases `HighwayHash` would be a better choice) -Additionally, aHash is not intended to be cryptographly secure and should not be used as a MAC, or anywhere which requires a cryptographically secure hash. +Additionally, aHash is not intended to be cryptographically secure and should not be used as a MAC, or anywhere which requires a cryptographically secure hash. (In these cases `SHA-3` would be a better choice) ## Usage AHash is a drop in replacement for the default implementation of the `Hasher` trait. To construct a `HashMap` using aHash -its hasher do the following: +as its hasher do the following: ```rust use ahash::{AHasher, RandomState}; @@ -38,8 +38,8 @@ use std::collections::HashMap; let mut map: HashMap<i32, i32, RandomState> = HashMap::default(); map.insert(12, 34); ``` -For convinence wrappers called `AHashMap` and `AHashSet` are also provided. -These to the same thing with slightly less typing. +For convenience, wrappers called `AHashMap` and `AHashSet` are also provided. +These do the same thing with slightly less typing. ```rust use ahash::AHashMap; @@ -70,9 +70,9 @@ random numbers will not be available at runtime. A full comparison with other hashing algorithms can be found [here](https://github.com/tkaitchuck/aHash/blob/master/compare/readme.md) -![Hasher perfromance](https://docs.google.com/spreadsheets/d/e/2PACX-1vSK7Li2nS-Bur9arAYF9IfT37MP-ohAe1v19lZu5fd9MajI1fSveLAQZyEie4Ea9k5-SWHTff7nL2DW/pubchart?oid=1323618938&format=image) +![Hasher performance](https://docs.google.com/spreadsheets/d/e/2PACX-1vSK7Li2nS-Bur9arAYF9IfT37MP-ohAe1v19lZu5fd9MajI1fSveLAQZyEie4Ea9k5-SWHTff7nL2DW/pubchart?oid=1323618938&format=image) -For more a more representative performance comparison which includes the overhead of using a HashMap, see [HashBrown's benchmarks](https://github.com/rust-lang/hashbrown#performance) +For a more representative performance comparison which includes the overhead of using a HashMap, see [HashBrown's benchmarks](https://github.com/rust-lang/hashbrown#performance) as HashBrown now uses aHash as its hasher by default. ## Hash quality diff --git a/src/aes_hash.rs b/src/aes_hash.rs index a51e361..3698c4e 100644 --- a/src/aes_hash.rs +++ b/src/aes_hash.rs @@ -138,11 +138,18 @@ impl Hasher for AHasher { } #[inline] + #[cfg(any(target_pointer_width = "64", target_pointer_width = "32", target_pointer_width = "16"))] fn write_usize(&mut self, i: usize) { self.write_u64(i as u64); } #[inline] + #[cfg(target_pointer_width = "128")] + fn write_usize(&mut self, i: usize) { + self.write_u128(i as u128); + } + + #[inline] fn write_u64(&mut self, i: u64) { self.write_u128(i as u128); } diff --git a/src/fallback_hash.rs b/src/fallback_hash.rs index 13e3d69..372debc 100644 --- a/src/fallback_hash.rs +++ b/src/fallback_hash.rs @@ -129,8 +129,8 @@ impl AHasher { #[cfg(not(feature = "folded_multiply"))] fn large_update(&mut self, new_data: u128) { let block: [u64; 2] = new_data.convert(); - self.update(block[0]); - self.update(block[1]); + self.update(block[0] ^ self.extra_keys[0]); + self.update(block[1] ^ self.extra_keys[1]); } #[inline] @@ -170,11 +170,18 @@ impl Hasher for AHasher { } #[inline] + #[cfg(any(target_pointer_width = "64", target_pointer_width = "32", target_pointer_width = "16"))] fn write_usize(&mut self, i: usize) { self.write_u64(i as u64); } #[inline] + #[cfg(target_pointer_width = "128")] + fn write_usize(&mut self, i: usize) { + self.write_u128(i as u128); + } + + #[inline] #[allow(clippy::collapsible_if)] fn write(&mut self, input: &[u8]) { let mut data = input; diff --git a/src/hash_quality_test.rs b/src/hash_quality_test.rs index 65b872a..837924d 100644 --- a/src/hash_quality_test.rs +++ b/src/hash_quality_test.rs @@ -273,11 +273,11 @@ fn test_padding_doesnot_collide<T: Hasher>(hasher: impl Fn() -> T) { let (same_bytes, same_nibbles) = count_same_bytes_and_nibbles(value, long.finish()); assert!( same_bytes <= 3, - format!("{} bytes of {} -> {:x} vs {:x}", num, c, value, long.finish()) + "{} bytes of {} -> {:x} vs {:x}", num, c, value, long.finish() ); assert!( same_nibbles <= 8, - format!("{} bytes of {} -> {:x} vs {:x}", num, c, value, long.finish()) + "{} bytes of {} -> {:x} vs {:x}", num, c, value, long.finish() ); let flipped_bits = (value ^ long.finish()).count_ones(); assert!(flipped_bits > 10); @@ -292,25 +292,21 @@ fn test_padding_doesnot_collide<T: Hasher>(hasher: impl Fn() -> T) { let (same_bytes, same_nibbles) = count_same_bytes_and_nibbles(value, long.finish()); assert!( same_bytes <= 3, - format!( - "string {:?} + {} bytes of {} -> {:x} vs {:x}", - string, - num, - c, - value, - long.finish() - ) + "string {:?} + {} bytes of {} -> {:x} vs {:x}", + string, + num, + c, + value, + long.finish() ); assert!( same_nibbles <= 8, - format!( - "string {:?} + {} bytes of {} -> {:x} vs {:x}", - string, - num, - c, - value, - long.finish() - ) + "string {:?} + {} bytes of {} -> {:x} vs {:x}", + string, + num, + c, + value, + long.finish() ); let flipped_bits = (value ^ long.finish()).count_ones(); assert!(flipped_bits > 10); @@ -363,8 +359,8 @@ mod fallback_tests { #[test] fn fallback_keys_affect_every_byte() { //For fallback second key is not used in every hash. - #[cfg(not(feature = "specialize"))] - test_keys_affect_every_byte(0, |a, b| AHasher::new_with_keys(a ^ b, a)); + #[cfg(all(not(feature = "specialize"), feature = "folded_multiply"))] + test_keys_affect_every_byte(0, |a, b| AHasher::new_with_keys(a ^ b, a)); test_keys_affect_every_byte("", |a, b| AHasher::new_with_keys(a ^ b, a)); test_keys_affect_every_byte((0, 0), |a, b| AHasher::new_with_keys(a ^ b, a)); } @@ -391,8 +387,10 @@ mod aes_tests { use crate::hash_quality_test::*; use std::hash::{Hash, Hasher}; - const BAD_KEY: u128 = 0x5252_5252_5252_5252_5252_5252_5252_5252; //This encrypts to 0. - const BAD_KEY2: u128 = 0x6363_6363_6363_6363_6363_6363_6363_6363; //This decrypts to 0. + //This encrypts to 0. + const BAD_KEY2: u128 = 0x6363_6363_6363_6363_6363_6363_6363_6363; + //This decrypts to 0. + const BAD_KEY: u128 = 0x5252_5252_5252_5252_5252_5252_5252_5252; #[test] fn test_single_bit_in_byte() { @@ -444,10 +442,11 @@ mod aes_tests { #[test] fn aes_keys_affect_every_byte() { #[cfg(not(feature = "specialize"))] - test_keys_affect_every_byte(0, AHasher::test_with_keys); + test_keys_affect_every_byte(0, AHasher::test_with_keys); test_keys_affect_every_byte("", AHasher::test_with_keys); test_keys_affect_every_byte((0, 0), AHasher::test_with_keys); } + #[test] fn aes_finish_is_consistant() { test_finish_is_consistent(AHasher::test_with_keys) diff --git a/src/operations.rs b/src/operations.rs index 8aa772d..2071d6b 100644 --- a/src/operations.rs +++ b/src/operations.rs @@ -7,6 +7,7 @@ const SHUFFLE_MASK: u128 = 0x020a0700_0c01030e_050f0d08_06090b04_u128; //const SHUFFLE_MASK: u128 = 0x000d0702_0a040301_05080f0c_0e0b0609_u128; //const SHUFFLE_MASK: u128 = 0x040A0700_030E0106_0D050F08_020B0C09_u128; +#[inline(always)] pub(crate) const fn folded_multiply(s: u64, by: u64) -> u64 { let result = (s as u128).wrapping_mul(by as u128); ((result & 0xffff_ffff_ffff_ffff) as u64) ^ ((result >> 64) as u64) diff --git a/tests/bench.rs b/tests/bench.rs index 683ef32..16904c0 100644 --- a/tests/bench.rs +++ b/tests/bench.rs @@ -64,152 +64,70 @@ fn gen_strings() -> Vec<String> { .collect() } -const U8_VALUES: [u8; 1] = [123]; -const U16_VALUES: [u16; 1] = [1234]; -const U32_VALUES: [u32; 1] = [12345678]; -const U64_VALUES: [u64; 1] = [1234567890123456]; -const U128_VALUES: [u128; 1] = [12345678901234567890123456789012]; +const U8_VALUE: u8 = 123; +const U16_VALUE: u16 = 1234; +const U32_VALUE: u32 = 12345678; +const U64_VALUE: u64 = 1234567890123456; +const U128_VALUE: u128 = 12345678901234567890123456789012; fn bench_ahash(c: &mut Criterion) { - c.bench( - "aeshash", - ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(aeshash(s))), &U8_VALUES), - ); - c.bench( - "aeshash", - ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(aeshash(s))), &U16_VALUES), - ); - c.bench( - "aeshash", - ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(aeshash(s))), &U32_VALUES), - ); - c.bench( - "aeshash", - ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(aeshash(s))), &U64_VALUES), - ); - c.bench( - "aeshash", - ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(aeshash(s))), &U128_VALUES), - ); - c.bench( - "aeshash", - ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(aeshash(s))), gen_strings()), - ); + let mut group = c.benchmark_group("aeshash"); + group.bench_with_input("u8", &U8_VALUE, |b, s| b.iter(|| black_box(aeshash(s)))); + group.bench_with_input("u16", &U16_VALUE, |b, s| b.iter(|| black_box(aeshash(s)))); + group.bench_with_input("u32", &U32_VALUE, |b, s| b.iter(|| black_box(aeshash(s)))); + group.bench_with_input("u64", &U64_VALUE, |b, s| b.iter(|| black_box(aeshash(s)))); + group.bench_with_input("u128", &U128_VALUE, |b, s| b.iter(|| black_box(aeshash(s)))); + group.bench_with_input("string", &gen_strings(), |b, s| b.iter(|| black_box(aeshash(s)))); } fn bench_fallback(c: &mut Criterion) { - c.bench( - "fallback", - ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U8_VALUES), - ); - c.bench( - "fallback", - ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U16_VALUES), - ); - c.bench( - "fallback", - ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U32_VALUES), - ); - c.bench( - "fallback", - ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U64_VALUES), - ); - c.bench( - "fallback", - ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U128_VALUES), - ); - c.bench( - "fallback", - ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fallbackhash(s))), gen_strings()), - ); + let mut group = c.benchmark_group("fallback"); + group.bench_with_input("u8", &U8_VALUE, |b, s| b.iter(|| black_box(fallbackhash(s)))); + group.bench_with_input("u16", &U16_VALUE, |b, s| b.iter(|| black_box(fallbackhash(s)))); + group.bench_with_input("u32", &U32_VALUE, |b, s| b.iter(|| black_box(fallbackhash(s)))); + group.bench_with_input("u64", &U64_VALUE, |b, s| b.iter(|| black_box(fallbackhash(s)))); + group.bench_with_input("u128", &U128_VALUE, |b, s| b.iter(|| black_box(fallbackhash(s)))); + group.bench_with_input("string", &gen_strings(), |b, s| b.iter(|| black_box(fallbackhash(s)))); } fn bench_fx(c: &mut Criterion) { - c.bench( - "fx", - ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fxhash(s))), &U8_VALUES), - ); - c.bench( - "fx", - ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fxhash(s))), &U16_VALUES), - ); - c.bench( - "fx", - ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fxhash(s))), &U32_VALUES), - ); - c.bench( - "fx", - ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fxhash(s))), &U64_VALUES), - ); - c.bench( - "fx", - ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fxhash(s))), &U128_VALUES), - ); - c.bench( - "fx", - ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fxhash(s))), gen_strings()), - ); + let mut group = c.benchmark_group("fx"); + group.bench_with_input("u8", &U8_VALUE, |b, s| b.iter(|| black_box(fxhash(s)))); + group.bench_with_input("u16", &U16_VALUE, |b, s| b.iter(|| black_box(fxhash(s)))); + group.bench_with_input("u32", &U32_VALUE, |b, s| b.iter(|| black_box(fxhash(s)))); + group.bench_with_input("u64", &U64_VALUE, |b, s| b.iter(|| black_box(fxhash(s)))); + group.bench_with_input("u128", &U128_VALUE, |b, s| b.iter(|| black_box(fxhash(s)))); + group.bench_with_input("string", &gen_strings(), |b, s| b.iter(|| black_box(fxhash(s)))); } fn bench_fnv(c: &mut Criterion) { - c.bench( - "fnv", - ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fnvhash(s))), &U8_VALUES), - ); - c.bench( - "fnv", - ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fnvhash(s))), &U16_VALUES), - ); - c.bench( - "fnv", - ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fnvhash(s))), &U32_VALUES), - ); - c.bench( - "fnv", - ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fnvhash(s))), &U64_VALUES), - ); - c.bench( - "fnv", - ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fnvhash(s))), &U128_VALUES), - ); - c.bench( - "fnv", - ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fnvhash(s))), gen_strings()), - ); + let mut group = c.benchmark_group("fnv"); + group.bench_with_input("u8", &U8_VALUE, |b, s| b.iter(|| black_box(fnvhash(s)))); + group.bench_with_input("u16", &U16_VALUE, |b, s| b.iter(|| black_box(fnvhash(s)))); + group.bench_with_input("u32", &U32_VALUE, |b, s| b.iter(|| black_box(fnvhash(s)))); + group.bench_with_input("u64", &U64_VALUE, |b, s| b.iter(|| black_box(fnvhash(s)))); + group.bench_with_input("u128", &U128_VALUE, |b, s| b.iter(|| black_box(fnvhash(s)))); + group.bench_with_input("string", &gen_strings(), |b, s| b.iter(|| black_box(fnvhash(s)))); } fn bench_sea(c: &mut Criterion) { - c.bench( - "sea", - ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(seahash(s))), gen_strings()), - ); + let mut group = c.benchmark_group("sea"); + group.bench_with_input("u8", &U8_VALUE, |b, s| b.iter(|| black_box(seahash(s)))); + group.bench_with_input("u16", &U16_VALUE, |b, s| b.iter(|| black_box(seahash(s)))); + group.bench_with_input("u32", &U32_VALUE, |b, s| b.iter(|| black_box(seahash(s)))); + group.bench_with_input("u64", &U64_VALUE, |b, s| b.iter(|| black_box(seahash(s)))); + group.bench_with_input("u128", &U128_VALUE, |b, s| b.iter(|| black_box(seahash(s)))); + group.bench_with_input("string", &gen_strings(), |b, s| b.iter(|| black_box(seahash(s)))); } fn bench_sip(c: &mut Criterion) { - c.bench( - "sip", - ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(siphash(s))), &U8_VALUES), - ); - c.bench( - "sip", - ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(siphash(s))), &U16_VALUES), - ); - c.bench( - "sip", - ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(siphash(s))), &U32_VALUES), - ); - c.bench( - "sip", - ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(siphash(s))), &U64_VALUES), - ); - c.bench( - "sip", - ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(siphash(s))), &U128_VALUES), - ); - c.bench( - "sip", - ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(siphash(s))), gen_strings()), - ); + let mut group = c.benchmark_group("sip"); + group.bench_with_input("u8", &U8_VALUE, |b, s| b.iter(|| black_box(siphash(s)))); + group.bench_with_input("u16", &U16_VALUE, |b, s| b.iter(|| black_box(siphash(s)))); + group.bench_with_input("u32", &U32_VALUE, |b, s| b.iter(|| black_box(siphash(s)))); + group.bench_with_input("u64", &U64_VALUE, |b, s| b.iter(|| black_box(siphash(s)))); + group.bench_with_input("u128", &U128_VALUE, |b, s| b.iter(|| black_box(siphash(s)))); + group.bench_with_input("string", &gen_strings(), |b, s| b.iter(|| black_box(siphash(s)))); } criterion_main!(benches); |