mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #91837 - Kobzol:stable-hash-map-avoid-sort, r=the8472
Avoid sorting in hash map stable hashing Suggested by `@the8472` [here](https://github.com/rust-lang/rust/pull/89404#issuecomment-991813333). I hope that I understood it right, I replaced the sort with modular multiplication, which should be commutative. Can I ask for a perf. run? However, locally it didn't help at all. Creating the `StableHasher` all over again is probably slowing it down quite a lot. And using `FxHasher` is not straightforward, because the keys and values only implement `HashStable` (and probably they shouldn't be just hashed via `Hash` anyway for it to actually be stable). Maybe the `StableHash` interface could be changed somehow to better suppor these scenarios where the hasher is short-lived. Or the `StableHasher` implementation could have variants with e.g. a shorter buffer for these scenarios.
This commit is contained in:
commit
daf2204aa4
@ -42,6 +42,7 @@ impl StableHasher {
|
||||
}
|
||||
|
||||
impl StableHasherResult for u128 {
|
||||
#[inline]
|
||||
fn finish(hasher: StableHasher) -> Self {
|
||||
let (_0, _1) = hasher.finalize();
|
||||
u128::from(_0) | (u128::from(_1) << 64)
|
||||
@ -49,6 +50,7 @@ impl StableHasherResult for u128 {
|
||||
}
|
||||
|
||||
impl StableHasherResult for u64 {
|
||||
#[inline]
|
||||
fn finish(hasher: StableHasher) -> Self {
|
||||
hasher.finalize().0
|
||||
}
|
||||
@ -507,7 +509,11 @@ where
|
||||
{
|
||||
#[inline]
|
||||
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
|
||||
hash_stable_hashmap(hcx, hasher, self, ToStableHashKey::to_stable_hash_key);
|
||||
stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, (key, value)| {
|
||||
let key = key.to_stable_hash_key(hcx);
|
||||
key.hash_stable(hcx, hasher);
|
||||
value.hash_stable(hcx, hasher);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,9 +523,10 @@ where
|
||||
R: BuildHasher,
|
||||
{
|
||||
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
|
||||
let mut keys: Vec<_> = self.iter().map(|k| k.to_stable_hash_key(hcx)).collect();
|
||||
keys.sort_unstable();
|
||||
keys.hash_stable(hcx, hasher);
|
||||
stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| {
|
||||
let key = key.to_stable_hash_key(hcx);
|
||||
key.hash_stable(hcx, hasher);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,10 +536,11 @@ where
|
||||
V: HashStable<HCX>,
|
||||
{
|
||||
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
|
||||
let mut entries: Vec<_> =
|
||||
self.iter().map(|(k, v)| (k.to_stable_hash_key(hcx), v)).collect();
|
||||
entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
|
||||
entries.hash_stable(hcx, hasher);
|
||||
stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, (key, value)| {
|
||||
let key = key.to_stable_hash_key(hcx);
|
||||
key.hash_stable(hcx, hasher);
|
||||
value.hash_stable(hcx, hasher);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -541,26 +549,38 @@ where
|
||||
K: ToStableHashKey<HCX>,
|
||||
{
|
||||
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
|
||||
let mut keys: Vec<_> = self.iter().map(|k| k.to_stable_hash_key(hcx)).collect();
|
||||
keys.sort_unstable();
|
||||
keys.hash_stable(hcx, hasher);
|
||||
stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| {
|
||||
let key = key.to_stable_hash_key(hcx);
|
||||
key.hash_stable(hcx, hasher);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hash_stable_hashmap<HCX, K, V, R, SK, F>(
|
||||
fn stable_hash_reduce<HCX, I, C, F>(
|
||||
hcx: &mut HCX,
|
||||
hasher: &mut StableHasher,
|
||||
map: &::std::collections::HashMap<K, V, R>,
|
||||
to_stable_hash_key: F,
|
||||
mut collection: C,
|
||||
length: usize,
|
||||
hash_function: F,
|
||||
) where
|
||||
K: Eq,
|
||||
V: HashStable<HCX>,
|
||||
R: BuildHasher,
|
||||
SK: HashStable<HCX> + Ord,
|
||||
F: Fn(&K, &HCX) -> SK,
|
||||
C: Iterator<Item = I>,
|
||||
F: Fn(&mut StableHasher, &mut HCX, I),
|
||||
{
|
||||
let mut entries: SmallVec<[_; 3]> =
|
||||
map.iter().map(|(k, v)| (to_stable_hash_key(k, hcx), v)).collect();
|
||||
entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
|
||||
entries.hash_stable(hcx, hasher);
|
||||
length.hash_stable(hcx, hasher);
|
||||
|
||||
match length {
|
||||
1 => {
|
||||
hash_function(hasher, hcx, collection.next().unwrap());
|
||||
}
|
||||
_ => {
|
||||
let hash = collection
|
||||
.map(|value| {
|
||||
let mut hasher = StableHasher::new();
|
||||
hash_function(&mut hasher, hcx, value);
|
||||
hasher.finish::<u128>()
|
||||
})
|
||||
.reduce(|accum, value| accum.wrapping_add(value));
|
||||
hash.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user