diff options
| author | bors <bors@rust-lang.org> | 2021-12-18 21:23:37 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-12-18 21:23:37 +0000 |
| commit | daf2204aa4954a9426cee93eb1baa2b26eb69070 (patch) | |
| tree | c216ecab68b04a59d4aec7fb65c6a63af718fe0d /compiler/rustc_data_structures/src | |
| parent | 91a0600a5c22b9d159e3c57526af83e71d1120f8 (diff) | |
| parent | 1f284b07edaae02324947221b2e0660e07fc5618 (diff) | |
| download | rust-daf2204aa4954a9426cee93eb1baa2b26eb69070.tar.gz rust-daf2204aa4954a9426cee93eb1baa2b26eb69070.zip | |
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.
Diffstat (limited to 'compiler/rustc_data_structures/src')
| -rw-r--r-- | compiler/rustc_data_structures/src/stable_hasher.rs | 66 |
1 files changed, 43 insertions, 23 deletions
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index b8ad66901c6..144eaed7e07 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -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); + } + } } |
