Skip to content

Commit 618c62d

Browse files
Merge pull request RustPython#1546 from makarchuk/resize-dict
Implement dict resizing
2 parents 11e8e62 + 0df4eed commit 618c62d

File tree

1 file changed

+30
-4
lines changed

1 file changed

+30
-4
lines changed

vm/src/dictdatatype.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,25 @@ pub struct DictSize {
4949
}
5050

5151
impl<T: Clone> Dict<T> {
52+
fn resize(&mut self) {
53+
let mut new_indices = HashMap::with_capacity(self.size);
54+
let mut new_entries = Vec::with_capacity(self.size);
55+
for maybe_entry in self.entries.drain(0..) {
56+
if let Some(entry) = maybe_entry {
57+
let mut hash_index = entry.hash;
58+
// Faster version of lookup. No equality checks here.
59+
// We assume dict doesn't contatins any duplicate keys
60+
while new_indices.contains_key(&hash_index) {
61+
hash_index = Self::next_index(entry.hash, hash_index);
62+
}
63+
new_indices.insert(hash_index, new_entries.len());
64+
new_entries.push(Some(entry));
65+
}
66+
}
67+
self.indices = new_indices;
68+
self.entries = new_entries;
69+
}
70+
5271
fn unchecked_push(
5372
&mut self,
5473
hash_index: HashIndex,
@@ -79,6 +98,9 @@ impl<T: Clone> Dict<T> {
7998
key: K,
8099
value: T,
81100
) -> PyResult<()> {
101+
if self.indices.len() > 2 * self.size {
102+
self.resize();
103+
}
82104
match self.lookup(vm, key)? {
83105
LookupResult::Existing(index) => {
84106
// Update existing key
@@ -240,14 +262,18 @@ impl<T: Clone> Dict<T> {
240262
}
241263

242264
// Update i to next probe location:
243-
hash_index = hash_index
244-
.wrapping_mul(5)
245-
.wrapping_add(perturb)
246-
.wrapping_add(1);
265+
hash_index = Self::next_index(perturb, hash_index)
247266
// warn!("Perturb value: {}", i);
248267
}
249268
}
250269

270+
fn next_index(perturb: HashValue, hash_index: HashIndex) -> HashIndex {
271+
hash_index
272+
.wrapping_mul(5)
273+
.wrapping_add(perturb)
274+
.wrapping_add(1)
275+
}
276+
251277
/// Retrieve and delete a key
252278
pub fn pop<K: DictKey + Copy>(&mut self, vm: &VirtualMachine, key: K) -> PyResult<Option<T>> {
253279
if let LookupResult::Existing(index) = self.lookup(vm, key)? {

0 commit comments

Comments
 (0)