Skip to content

Commit 8cff0ed

Browse files
authored
Avoid allocating a vector of elements when hashing frozenset (RustPython#5408)
Adds a `try_fold_keys` method to Dict which allows performing common operations on all elements without needing to create a Vec first.
1 parent a8964f4 commit 8cff0ed

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

vm/src/builtins/set.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,12 +436,12 @@ impl PySetInner {
436436
((h ^ 89869747) ^ (h.wrapping_shl(16))).wrapping_mul(3644798167)
437437
}
438438
// Factor in the number of active entries
439-
let mut hash: u64 = (self.elements().len() as u64 + 1).wrapping_mul(1927868237);
439+
let mut hash: u64 = (self.len() as u64 + 1).wrapping_mul(1927868237);
440440
// Xor-in shuffled bits from every entry's hash field because xor is
441441
// commutative and a frozenset hash should be independent of order.
442-
for element in self.elements().iter() {
443-
hash ^= _shuffle_bits(element.hash(vm)? as u64);
444-
}
442+
hash = self.content.try_fold_keys(hash, |h, element| {
443+
Ok(h ^ _shuffle_bits(element.hash(vm)? as u64))
444+
})?;
445445
// Disperse patterns arising in nested frozensets
446446
hash ^= (hash >> 11) ^ (hash >> 25);
447447
hash = hash.wrapping_mul(69069).wrapping_add(907133923);

vm/src/dictdatatype.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,17 @@ impl<T: Clone> Dict<T> {
530530
.collect()
531531
}
532532

533+
pub fn try_fold_keys<Acc, Fold>(&self, init: Acc, f: Fold) -> PyResult<Acc>
534+
where
535+
Fold: FnMut(Acc, &PyObject) -> PyResult<Acc>,
536+
{
537+
self.read()
538+
.entries
539+
.iter()
540+
.filter_map(|v| v.as_ref().map(|v| v.key.as_object()))
541+
.try_fold(init, f)
542+
}
543+
533544
/// Lookup the index for the given key.
534545
#[cfg_attr(feature = "flame-it", flame("Dict"))]
535546
fn lookup<K: DictKey + ?Sized>(

0 commit comments

Comments
 (0)