Skip to content

Commit bde6bad

Browse files
committed
try more slots
1 parent aff5050 commit bde6bad

File tree

1 file changed

+28
-13
lines changed

1 file changed

+28
-13
lines changed

src/py_string_cache.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,22 +119,37 @@ impl PyStringCache {
119119
fn get_or_insert(&mut self, py: Python, s: &str) -> PyObject {
120120
let hash = self.hash_builder.hash_one(s);
121121

122-
let index = hash as usize % CAPACITY;
123-
124-
let entry = unsafe { self.entries.get_unchecked_mut(index) };
125-
if let Some((h, ref py_str_ob)) = entry {
126-
// to avoid a string comparison, we first compare the hashes
127-
if *h == hash {
128-
// if the hashes match, we compare the strings to be correct - as hashmap would do
129-
if py_str_ob.as_ref(py).to_str().ok() == Some(s) {
130-
return py_str_ob.to_object(py);
122+
let hash_index = hash as usize % CAPACITY;
123+
124+
let set_entry = |entry: &mut Option<(u64, Py<PyString>)>| {
125+
let py_str = PyString::new(py, s);
126+
*entry = Some((hash, py_str.into_py(py)));
127+
py_str.to_object(py)
128+
};
129+
130+
for index in hash_index..(hash_index + 5) {
131+
if let Some(entry) = self.entries.get_mut(index) {
132+
if let Some((entry_hash, ref py_str_ob)) = entry {
133+
// to avoid a string comparison, we first compare the hashes
134+
if *entry_hash == hash {
135+
// if the hashes match, we compare the strings to be absolutely sure - as a hashmap would do
136+
if py_str_ob.as_ref(py).to_str().ok() == Some(s) {
137+
return py_str_ob.to_object(py);
138+
}
139+
}
140+
} else {
141+
// we got to an empty entry, use it
142+
return set_entry(entry);
131143
}
144+
} else {
145+
// we reached the end of entries, break
146+
break;
132147
}
133148
}
134-
135-
let py_str = PyString::new(py, s);
136-
*entry = Some((hash, py_str.into_py(py)));
137-
py_str.to_object(py)
149+
// we tried all 5 slots (or got to the end of entries) without finding a match
150+
// or an empty slot, make this LRU by replacing the first entry
151+
let entry = unsafe { self.entries.get_unchecked_mut(hash_index) };
152+
set_entry(entry)
138153
}
139154

140155
/// get the number of entries in the cache that are set

0 commit comments

Comments
 (0)