@@ -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