@@ -220,28 +220,6 @@ where
220220 num_entries * ( current_array. len ( ) / ( sample_size * 2 ) )
221221 }
222222
223- /// Checks whether rebuilding the entire hash table is required.
224- #[ inline]
225- fn check_rebuild ( current_array : & BucketArray < K , V , L , TYPE > , sampling_index : usize ) -> bool {
226- let sample_size = current_array. sample_size ( ) ;
227- let sample_1 = sampling_index & ( !( sample_size - 1 ) ) ;
228- let sample_2 = if sample_1 == 0 {
229- current_array. len ( ) - sample_size
230- } else {
231- 0
232- } ;
233- let mut num_buckets_to_rebuild = 0 ;
234- for i in ( sample_1..sample_1 + sample_size) . chain ( sample_2..( sample_2 + sample_size) ) {
235- if current_array. bucket ( i) . need_rebuild ( ) {
236- num_buckets_to_rebuild += 1 ;
237- if num_buckets_to_rebuild >= sample_size {
238- return true ;
239- }
240- }
241- }
242- false
243- }
244-
245223 /// Peeks an entry from the [`HashTable`].
246224 #[ inline]
247225 fn peek_entry < ' g , Q > ( & self , key : & Q , guard : & ' g Guard ) -> Option < & ' g ( K , V ) >
@@ -707,8 +685,11 @@ where
707685 }
708686
709687 if removed {
688+ if TYPE == INDEX {
689+ async_guard. guard ( ) . set_has_garbage ( ) ;
690+ }
710691 if let Some ( current_array) = self . bucket_array ( async_guard. guard ( ) ) {
711- self . try_shrink_or_rebuild ( current_array, 0 , async_guard. guard ( ) ) ;
692+ self . try_shrink ( current_array, 0 , async_guard. guard ( ) ) ;
712693 }
713694 }
714695 }
@@ -773,8 +754,11 @@ where
773754 }
774755
775756 if removed {
757+ if TYPE == INDEX {
758+ guard. set_has_garbage ( ) ;
759+ }
776760 if let Some ( current_array) = self . bucket_array ( guard) {
777- self . try_shrink_or_rebuild ( current_array, 0 , guard) ;
761+ self . try_shrink ( current_array, 0 , guard) ;
778762 }
779763 }
780764 }
@@ -1296,43 +1280,24 @@ where
12961280 }
12971281 }
12981282
1299- /// Tries to shrink the [`HashTable`] to fit the estimated number of entries or rebuild it to
1300- /// optimize the storage.
1301- fn try_shrink_or_rebuild (
1302- & self ,
1303- current_array : & BucketArray < K , V , L , TYPE > ,
1304- index : usize ,
1305- guard : & Guard ,
1306- ) {
1283+ /// Tries to shrink the [`HashTable`] to fit the estimated number of entries it to optimize the
1284+ /// storage.
1285+ fn try_shrink ( & self , current_array : & BucketArray < K , V , L , TYPE > , index : usize , guard : & Guard ) {
13071286 if !current_array. has_linked_array ( ) {
13081287 let minimum_capacity = self . minimum_capacity ( ) ;
1309- if TYPE == INDEX || current_array. num_slots ( ) > minimum_capacity {
1288+ if current_array. num_slots ( ) > minimum_capacity {
13101289 // Try to shrink if the estimated load factor is less than `1/8`.
13111290 let shrink_threshold = current_array. sample_size ( ) * BUCKET_LEN / 8 ;
1312- // Try to rebuild if half the samples need to be rebuilt.
1313- let rebuild_threshold = ( current_array. sample_size ( ) / 2 ) . max ( 1 ) ;
13141291 let mut num_entries = 0 ;
1315- let mut num_buckets_to_rebuild = 0 ;
13161292 for i in 0 ..current_array. sample_size ( ) {
13171293 let bucket = current_array. bucket ( ( index + i) % current_array. len ( ) ) ;
13181294 num_entries += bucket. len ( ) ;
1319- if num_entries >= shrink_threshold
1320- && ( TYPE != INDEX
1321- || num_buckets_to_rebuild + ( current_array. sample_size ( ) - i)
1322- < rebuild_threshold)
1323- {
1295+ if num_entries >= shrink_threshold {
13241296 // Early exit.
13251297 return ;
13261298 }
1327- if TYPE == INDEX && bucket. need_rebuild ( ) {
1328- num_buckets_to_rebuild += 1 ;
1329- if num_buckets_to_rebuild >= rebuild_threshold {
1330- self . try_resize ( current_array, index, guard) ;
1331- return ;
1332- }
1333- }
13341299 }
1335- if TYPE != INDEX || num_entries <= shrink_threshold {
1300+ if num_entries <= shrink_threshold {
13361301 self . try_resize ( current_array, index, guard) ;
13371302 }
13381303 }
@@ -1393,10 +1358,7 @@ where
13931358
13941359 let try_resize = new_capacity != capacity;
13951360 let try_drop_table = estimated_num_entries == 0 && minimum_capacity == 0 ;
1396- let try_rebuild =
1397- TYPE == INDEX && !try_resize && Self :: check_rebuild ( current_array, sampling_index) ;
1398-
1399- if !try_resize && !try_drop_table && !try_rebuild {
1361+ if !try_resize && !try_drop_table {
14001362 // Nothing to do.
14011363 return ;
14021364 }
@@ -1454,7 +1416,7 @@ where
14541416 self . defer_reclaim ( bucket_array, guard) ;
14551417 }
14561418 }
1457- } else if try_resize || try_rebuild {
1419+ } else if try_resize {
14581420 let new_bucket_array = unsafe {
14591421 Shared :: new_unchecked ( BucketArray :: < K , V , L , TYPE > :: new (
14601422 new_capacity,
@@ -1550,11 +1512,13 @@ impl<K: Eq + Hash, V, L: LruList, const TYPE: char> LockedBucket<K, V, L, TYPE>
15501512 H : BuildHasher ,
15511513 {
15521514 let removed = self . writer . remove ( self . data_block , entry_ptr) ;
1553- self . try_shrink_or_rebuild ( hash_table) ;
1515+ if self . len ( ) == 0 {
1516+ self . try_shrink ( hash_table, & Guard :: new ( ) ) ;
1517+ }
15541518 removed
15551519 }
15561520
1557- /// Removes the entry and tries to shrink or rebuild the container.
1521+ /// Removes the entry and tries to shrink the container.
15581522 #[ inline]
15591523 pub ( crate ) fn mark_removed < H , T : HashTable < K , V , H , L , TYPE > > (
15601524 self ,
@@ -1565,26 +1529,36 @@ impl<K: Eq + Hash, V, L: LruList, const TYPE: char> LockedBucket<K, V, L, TYPE>
15651529 {
15661530 debug_assert_eq ! ( TYPE , INDEX ) ;
15671531
1568- self . writer . mark_removed ( entry_ptr) ;
1569- self . try_shrink_or_rebuild ( hash_table) ;
1532+ let guard = Guard :: new ( ) ;
1533+ self . writer . mark_removed ( entry_ptr, & guard) ;
1534+ self . set_has_garbage ( & guard) ;
1535+ if self . writer . len ( ) == 0 {
1536+ self . try_shrink ( hash_table, & guard) ;
1537+ }
15701538 }
15711539
1572- /// Tries to shrink or rebuild the container .
1540+ /// Sets that there can be a garbage entry in the bucket so the epoch should be advanced .
15731541 #[ inline]
1574- pub ( crate ) fn try_shrink_or_rebuild < H , T : HashTable < K , V , H , L , TYPE > > ( self , hash_table : & T )
1542+ pub ( crate ) const fn set_has_garbage ( & self , guard : & Guard ) {
1543+ let sample_size = self . bucket_array ( ) . sample_size ( ) ;
1544+ if self . bucket_index % ( sample_size * sample_size) == 0 {
1545+ guard. set_has_garbage ( ) ;
1546+ }
1547+ }
1548+
1549+ /// Tries to shrink the container.
1550+ #[ inline]
1551+ pub ( crate ) fn try_shrink < H , T : HashTable < K , V , H , L , TYPE > > ( self , hash_table : & T , guard : & Guard )
15751552 where
15761553 H : BuildHasher ,
15771554 {
1578- if ( TYPE == INDEX && self . writer . need_rebuild ( ) ) || self . writer . len ( ) == 0 {
1579- let guard = Guard :: new ( ) ;
1580- if let Some ( current_array) = hash_table. bucket_array ( & guard) {
1581- if ptr:: eq ( current_array, self . bucket_array ( ) ) {
1582- let bucket_index = self . bucket_index ;
1583- drop ( self ) ;
1584-
1585- // Tries to shrink or rebuild the container after unlocking the bucket.
1586- hash_table. try_shrink_or_rebuild ( current_array, bucket_index, & guard) ;
1587- }
1555+ if let Some ( current_array) = hash_table. bucket_array ( guard) {
1556+ if ptr:: eq ( current_array, self . bucket_array ( ) ) {
1557+ let bucket_index = self . bucket_index ;
1558+ drop ( self ) ;
1559+
1560+ // Tries to shrink the container after unlocking the bucket.
1561+ hash_table. try_shrink ( current_array, bucket_index, guard) ;
15881562 }
15891563 }
15901564 }
@@ -1607,7 +1581,7 @@ impl<K: Eq + Hash, V, L: LruList, const TYPE: char> LockedBucket<K, V, L, TYPE>
16071581 let len = self . bucket_array ( ) . len ( ) ;
16081582
16091583 if self . writer . len ( ) == 0 {
1610- self . try_shrink_or_rebuild ( hash_table) ;
1584+ self . try_shrink ( hash_table, & Guard :: new ( ) ) ;
16111585 } else {
16121586 drop ( self ) ;
16131587 }
@@ -1649,7 +1623,7 @@ impl<K: Eq + Hash, V, L: LruList, const TYPE: char> LockedBucket<K, V, L, TYPE>
16491623 let len = self . bucket_array ( ) . len ( ) ;
16501624
16511625 if self . writer . len ( ) == 0 {
1652- self . try_shrink_or_rebuild ( hash_table) ;
1626+ self . try_shrink ( hash_table, & Guard :: new ( ) ) ;
16531627 } else {
16541628 drop ( self ) ;
16551629 }
0 commit comments