Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature gate random state #97

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ doc = true
default = ["std"]

# Enabling this will enable `AHashMap` and `AHashSet`.
std = []
std = ["random-state"]

# Enable this will enable `RandomState`.
random-state = ["getrandom", "once_cell"]

# This is an alternitive to runtime key generation which does compile time key generation if getrandom is not available.
# (If getrandom is available this does nothing.)
Expand Down Expand Up @@ -66,7 +69,7 @@ codegen-units = 1
version_check = "0.9"

[target.'cfg(any(target_os = "linux", target_os = "android", target_os = "windows", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "dragonfly", target_os = "solaris", target_os = "illumos", target_os = "fuchsia", target_os = "redox", target_os = "cloudabi", target_os = "haiku", target_os = "vxworks", target_os = "emscripten", target_os = "wasi"))'.dependencies]
getrandom = { version = "0.2.3" }
getrandom = { version = "0.2.3", optional = true }
const-random = { version = "0.1.12", optional = true }
serde = { version = "1.0.117", optional = true }

Expand All @@ -75,7 +78,7 @@ const-random = { version = "0.1.12", optional = true }
serde = { version = "1.0.117", optional = true }

[target.'cfg(not(all(target_arch = "arm", target_os = "none")))'.dependencies]
once_cell = { version = "1.8", default-features = false, features = ["alloc"] }
once_cell = { version = "1.8", default-features = false, features = ["alloc"], optional = true }

[dev-dependencies]
no-panic = "0.1.10"
Expand Down
2 changes: 1 addition & 1 deletion compare/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ debug-assertions = false
codegen-units = 1

[dependencies]
ahash = { path = "../", default-features = false }
ahash = { path = "../", default-features = false, features = ["random-state"] }

[dev-dependencies]
criterion = "0.3.3"
Expand Down
2 changes: 1 addition & 1 deletion smhasher/ahash-cbindings/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ lto = 'fat'
debug-assertions = false

[dependencies]
ahash = { path = "../../", default-features = false }
ahash = { path = "../../", default-features = false, features = ["random-state"] }
10 changes: 6 additions & 4 deletions src/aes_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use crate::convert::*;
#[cfg(feature = "specialize")]
use crate::fallback_hash::MULTIPLE;
use crate::operations::*;
use crate::PI;
#[cfg(feature = "random-state")]
use crate::RandomState;
use core::hash::Hasher;
use crate::random_state::PI;

/// A `Hasher` for hashing an arbitrary stream of bytes.
///
Expand Down Expand Up @@ -70,7 +71,7 @@ impl AHasher {
}
}


#[cfg(feature = "random-state")]
#[inline]
pub(crate) fn from_random_state(rand_state: &RandomState) -> Self {
let key1 = [rand_state.k0, rand_state.k1].convert();
Expand Down Expand Up @@ -369,11 +370,12 @@ mod tests {
use super::*;
use crate::convert::Convert;
use crate::operations::aesenc;
use crate::RandomState;
use std::hash::{BuildHasher, Hasher};

#[cfg(feature = "random-state")]
#[test]
fn test_sanity() {
let mut hasher = RandomState::with_seeds(1, 2, 3, 4).build_hasher();
let mut hasher = crate::RandomState::with_seeds(1, 2, 3, 4).build_hasher();
hasher.write_u64(0);
let h1 = hasher.finish();
hasher.write(&[1, 0, 0, 0, 0, 0, 0, 0]);
Expand Down
4 changes: 3 additions & 1 deletion src/fallback_hash.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::convert::*;
use crate::operations::folded_multiply;
use crate::operations::read_small;
use crate::random_state::PI;
use crate::PI;
#[cfg(feature = "random-state")]
use crate::RandomState;
use core::hash::Hasher;

Expand Down Expand Up @@ -53,6 +54,7 @@ impl AHasher {
}
}

#[cfg(feature = "random-state")]
#[inline]
#[allow(dead_code)] // Is not called if non-fallback hash is used.
pub(crate) fn from_random_state(rand_state: &RandomState) -> AHasher {
Expand Down
29 changes: 27 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,26 @@
//!
//! # Example
//! ```
//! # #[cfg(feature = "random-state")]
//! # {
//! use ahash::{AHasher, RandomState};
//! 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.
//! ```ignore
//! ```
//! # #[cfg(feature = "std")]
//! # {
//! use ahash::AHashMap;
//!
//! let mut map: AHashMap<i32, i32> = AHashMap::with_capacity(4);
//! map.insert(12, 34);
//! map.insert(56, 78);
//! # }
//! ```
#![deny(clippy::correctness, clippy::complexity, clippy::perf)]
#![allow(clippy::pedantic, clippy::cast_lossless, clippy::unreadable_literal)]
Expand All @@ -49,6 +55,7 @@ mod hash_map;
#[cfg(feature = "std")]
mod hash_set;
mod operations;
#[cfg(feature = "random-state")]
mod random_state;
mod specialize;

Expand All @@ -63,6 +70,8 @@ pub use crate::aes_hash::AHasher;
all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
)))]
pub use crate::fallback_hash::AHasher;

#[cfg(feature = "random-state")]
pub use crate::random_state::RandomState;

pub use crate::specialize::CallHasher;
Expand All @@ -75,6 +84,22 @@ use core::hash::BuildHasher;
use core::hash::Hash;
use core::hash::Hasher;

pub(crate) const PI: [u64; 4] = [
0x243f_6a88_85a3_08d3,
0x1319_8a2e_0370_7344,
0xa409_3822_299f_31d0,
0x082e_fa98_ec4e_6c89,
];

#[cfg(feature = "random-state")]
pub(crate) const PI2: [u64; 4] = [
0x4528_21e6_38d0_1377,
0xbe54_66cf_34e9_0c6c,
0xc0ac_29b7_c97c_50dd,
0x3f84_d5b5_b547_0917,
];

#[cfg(feature = "random-state")]
/// Provides a default [Hasher] with fixed keys.
/// This is typically used in conjunction with [BuildHasherDefault] to create
/// [AHasher]s in order to hash the keys of the map.
Expand All @@ -86,7 +111,7 @@ use core::hash::Hasher;
/// # Example
/// ```
/// use std::hash::BuildHasherDefault;
/// use ahash::{AHasher, RandomState};
/// use ahash::AHasher;
/// use std::collections::HashMap;
///
/// let mut map: HashMap<i32, i32, BuildHasherDefault<AHasher>> = HashMap::default();
Expand Down
15 changes: 1 addition & 14 deletions src/random_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use crate::convert::Convert;
#[cfg(feature = "specialize")]
use crate::BuildHasherExt;
use crate::{PI, PI2};

#[cfg(any(
all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
Expand Down Expand Up @@ -58,20 +59,6 @@ pub trait RandomSource {

}

pub(crate) const PI: [u64; 4] = [
0x243f_6a88_85a3_08d3,
0x1319_8a2e_0370_7344,
0xa409_3822_299f_31d0,
0x082e_fa98_ec4e_6c89,
];

pub(crate) const PI2: [u64; 4] = [
0x4528_21e6_38d0_1377,
0xbe54_66cf_34e9_0c6c,
0xc0ac_29b7_c97c_50dd,
0x3f84_d5b5_b547_0917,
];

struct DefaultRandomSource {
counter: AtomicUsize,
}
Expand Down
8 changes: 7 additions & 1 deletion src/specialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use alloc::vec::Vec;
/// for a specific type. So this may be faster for primitive types.
/// # Example
/// ```
/// # #[cfg(feature = "random-state")]
/// # {
/// use std::hash::BuildHasher;
/// use ahash::RandomState;
/// use ahash::CallHasher;
Expand All @@ -27,16 +29,20 @@ use alloc::vec::Vec;
/// //...
/// let value: u32 = 17;
/// let hash = u32::get_hash(&value, &hash_builder);
/// # }
/// ```
/// Note that the type used to invoke `get_hash` must be the same a the type of value passed.
/// For example get a hasher specialized on `[u8]` can invoke:
/// ```
/// # #[cfg(feature = "random-state")]
/// # {
/// /// use std::hash::BuildHasher;
/// # use ahash::RandomState;
/// # use ahash::CallHasher;
/// # let hash_builder = RandomState::new();
/// let bytes: [u8; 4] = [1, 2, 3, 4];
/// let hash = <[u8]>::get_hash(&bytes, &hash_builder);
/// # }
/// ```
pub trait CallHasher {
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64;
Expand Down Expand Up @@ -152,7 +158,7 @@ impl CallHasher for String {
}
}

#[cfg(test)]
#[cfg(all(test, feature = "random-state"))]
mod test {
use super::*;
use crate::*;
Expand Down
2 changes: 2 additions & 0 deletions tests/bench.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![cfg(feature = "random-state")]

use ahash::{CallHasher, RandomState};
use criterion::*;
use fxhash::FxHasher;
Expand Down
5 changes: 3 additions & 2 deletions tests/map_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::hash::{BuildHasher, Hash, Hasher};
use criterion::*;
use fxhash::FxHasher;

use ahash::{AHasher, CallHasher, RandomState};
use ahash::{AHasher, CallHasher};

fn gen_word_pairs() -> Vec<String> {
let words: Vec<_> = r#"
Expand Down Expand Up @@ -155,9 +155,10 @@ fn hash<H: Hash, B: BuildHasher>(b: &H, build_hasher: &B) -> u64 {
H::get_hash(b, build_hasher)
}

#[cfg(feature = "random-state")]
#[test]
fn test_bucket_distribution() {
let build_hasher = RandomState::with_seeds(1, 2, 3, 4);
let build_hasher = ahash::RandomState::with_seeds(1, 2, 3, 4);
test_hash_common_words(&build_hasher);
let sequence: Vec<_> = (0..320000).collect();
check_for_collisions(&build_hasher, &sequence, 32);
Expand Down
5 changes: 4 additions & 1 deletion tests/nopanic.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ahash::{AHasher, CallHasher, RandomState};
use ahash::{AHasher, CallHasher};
use std::hash::BuildHasher;

#[macro_use]
Expand Down Expand Up @@ -48,9 +48,12 @@ fn hash_test_random_wrapper(num: i32, string: &str) {
hash_test_specialize(num, string);
}

#[cfg(feature = "random-state")]
#[inline(never)]
#[no_panic]
fn hash_test_random(num: i32, string: &str) -> (u64, u64) {
use ahash::RandomState;

let build_hasher1 = RandomState::with_seeds(1, 2, 3, 4);
let build_hasher2 = RandomState::with_seeds(1, 2, 3, 4);
(
Expand Down