From a5f5f6b6892ffe5364e25345c6f5a0113ae33a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 12 Dec 2021 20:24:56 +0100 Subject: [PATCH 1/4] Avoid sorting in hash map stable hashing --- .../rustc_data_structures/src/stable_hasher.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index b8ad66901c6..c2218b92a44 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 } @@ -559,8 +561,16 @@ pub fn hash_stable_hashmap( SK: HashStable + Ord, F: Fn(&K, &HCX) -> SK, { - 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); + let hash = map + .iter() + .map(|(key, value)| { + let key = to_stable_hash_key(key, hcx); + let mut hasher = StableHasher::new(); + key.hash_stable(hcx, &mut hasher); + value.hash_stable(hcx, &mut hasher); + hasher.finish::() + }) + .reduce(|accum, value| accum.wrapping_mul(value)); + map.len().hash_stable(hcx, hasher); + hash.hash_stable(hcx, hasher); } From 6e33d3ecc26f294c275b55fe02a33645e252f81a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 12 Dec 2021 22:54:09 +0100 Subject: [PATCH 2/4] Use modular arithmetic --- compiler/rustc_data_structures/src/stable_hasher.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index c2218b92a44..150c835c236 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -503,7 +503,7 @@ impl_stable_hash_via_hash!(::std::path::PathBuf); impl HashStable for ::std::collections::HashMap where - K: ToStableHashKey + Eq, + K: HashStable + ToStableHashKey + Eq, V: HashStable, R: BuildHasher, { @@ -555,7 +555,7 @@ pub fn hash_stable_hashmap( map: &::std::collections::HashMap, to_stable_hash_key: F, ) where - K: Eq, + K: Eq + HashStable, V: HashStable, R: BuildHasher, SK: HashStable + Ord, @@ -570,7 +570,7 @@ pub fn hash_stable_hashmap( value.hash_stable(hcx, &mut hasher); hasher.finish::() }) - .reduce(|accum, value| accum.wrapping_mul(value)); + .reduce(|accum, value| accum.wrapping_add(value)); map.len().hash_stable(hcx, hasher); hash.hash_stable(hcx, hasher); } From ac08f13948303491ed4a00f0578bd64f0327769c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 13 Dec 2021 09:19:59 +0100 Subject: [PATCH 3/4] Remove sort from hashing hashset, treeset and treemap --- .../src/stable_hasher.rs | 56 ++++++++++--------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index 150c835c236..f37cf76c32b 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -503,13 +503,17 @@ impl_stable_hash_via_hash!(::std::path::PathBuf); impl HashStable for ::std::collections::HashMap where - K: HashStable + ToStableHashKey + Eq, + K: ToStableHashKey + Eq, V: HashStable, R: BuildHasher, { #[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); + }); } } @@ -519,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); + }); } } @@ -531,10 +536,11 @@ where V: HashStable, { 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); + }); } } @@ -543,34 +549,30 @@ where K: ToStableHashKey, { 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( +fn stable_hash_reduce( hcx: &mut HCX, hasher: &mut StableHasher, - map: &::std::collections::HashMap, - to_stable_hash_key: F, + collection: C, + length: usize, + hash_function: F, ) where - K: Eq + HashStable, - V: HashStable, - R: BuildHasher, - SK: HashStable + Ord, - F: Fn(&K, &HCX) -> SK, + C: Iterator, + F: Fn(&mut StableHasher, &mut HCX, I), { - let hash = map - .iter() - .map(|(key, value)| { - let key = to_stable_hash_key(key, hcx); + let hash = collection + .map(|value| { let mut hasher = StableHasher::new(); - key.hash_stable(hcx, &mut hasher); - value.hash_stable(hcx, &mut hasher); + hash_function(&mut hasher, hcx, value); hasher.finish::() }) .reduce(|accum, value| accum.wrapping_add(value)); - map.len().hash_stable(hcx, hasher); + length.hash_stable(hcx, hasher); hash.hash_stable(hcx, hasher); } From 1f284b07edaae02324947221b2e0660e07fc5618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 13 Dec 2021 21:34:54 +0100 Subject: [PATCH 4/4] Add special case for length 1 --- .../src/stable_hasher.rs | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index f37cf76c32b..144eaed7e07 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -559,20 +559,28 @@ where fn stable_hash_reduce( hcx: &mut HCX, hasher: &mut StableHasher, - collection: C, + mut collection: C, length: usize, hash_function: F, ) where C: Iterator, F: Fn(&mut StableHasher, &mut HCX, I), { - let hash = collection - .map(|value| { - let mut hasher = StableHasher::new(); - hash_function(&mut hasher, hcx, value); - hasher.finish::() - }) - .reduce(|accum, value| accum.wrapping_add(value)); length.hash_stable(hcx, hasher); - hash.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::() + }) + .reduce(|accum, value| accum.wrapping_add(value)); + hash.hash_stable(hcx, hasher); + } + } }