perf: improve {Dict, Set}::hash

This commit is contained in:
Shunsuke Shibayama 2024-10-03 15:38:34 +09:00
parent f862a3f13a
commit 037712b282
2 changed files with 19 additions and 7 deletions

View file

@ -36,13 +36,22 @@ impl<K: Hash + Eq + Immutable, V: Hash + Eq> Eq for Dict<K, V> {}
impl<K: Hash, V: Hash> Hash for Dict<K, V> {
fn hash<H: Hasher>(&self, state: &mut H) {
let len = self.len();
len.hash(state);
if len <= 1 {
for (key, val) in self.iter() {
key.hash(state);
val.hash(state);
}
return;
}
let mut v = self
.iter()
.map(|(key, val)| (get_hash(key), key, val))
.map(|(key, val)| (get_hash(key), val))
.collect::<Vec<_>>();
v.sort_by_key(|(h, _, _)| *h);
for (_, key, val) in v.iter() {
key.hash(state);
v.sort_unstable_by_key(|(h, _)| *h);
for (h, val) in v.iter() {
state.write_usize(*h);
val.hash(state);
}
}

View file

@ -63,9 +63,12 @@ impl<T> Default for Set<T> {
impl<T: Hash> Hash for Set<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
let mut v = self.iter().map(get_hash).collect::<Vec<_>>();
v.sort();
v.hash(state);
self.len().hash(state);
let sum = self
.iter()
.map(get_hash)
.fold(0usize, |acc, x| acc.wrapping_add(x));
sum.hash(state);
}
}