From 89f7d4ab9a4856541ca2e9a31d6e9ad207014cc7 Mon Sep 17 00:00:00 2001 From: "Jeff Washington (jwash)" Date: Thu, 30 Mar 2023 15:20:10 -0500 Subject: [PATCH] Move `data_bucket_ix()` method to `MultipleSlots` (#30992) move data_bucket_ix to MultipleSlots --- bucket_map/src/bucket.rs | 11 +++--- bucket_map/src/index_entry.rs | 64 +++++++++++++++++++++-------------- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/bucket_map/src/bucket.rs b/bucket_map/src/bucket.rs index 5598f5edc..a26f3168f 100644 --- a/bucket_map/src/bucket.rs +++ b/bucket_map/src/bucket.rs @@ -4,7 +4,9 @@ use { bucket_map::BucketMapError, bucket_stats::BucketMapStats, bucket_storage::{BucketOccupied, BucketStorage, DEFAULT_CAPACITY_POW2}, - index_entry::{DataBucket, IndexBucket, IndexEntry, IndexEntryPlaceInBucket}, + index_entry::{ + DataBucket, IndexBucket, IndexEntry, IndexEntryPlaceInBucket, MultipleSlots, + }, MaxSearch, RefCount, }, rand::{thread_rng, Rng}, @@ -265,7 +267,7 @@ impl<'b, T: Clone + Copy + 'static> Bucket { data_len: usize, ref_count: RefCount, ) -> Result<(), BucketMapError> { - let best_fit_bucket = IndexEntry::::data_bucket_from_num_slots(data_len as u64); + let best_fit_bucket = MultipleSlots::data_bucket_from_num_slots(data_len as u64); if self.data.get(best_fit_bucket as usize).is_none() { // fail early if the data bucket we need doesn't exist - we don't want the index entry partially allocated return Err(BucketMapError::DataNoSpace((best_fit_bucket, 0))); @@ -286,8 +288,7 @@ impl<'b, T: Clone + Copy + 'static> Bucket { elem.set_ref_count(&mut self.index, ref_count); let current_multiple_slots = elem.get_multiple_slots(&self.index); - let bucket_ix = - IndexEntry::::data_bucket_from_num_slots(current_multiple_slots.num_slots()); + let bucket_ix = current_multiple_slots.data_bucket_ix(); let num_slots = data_len as u64; if best_fit_bucket == bucket_ix && current_multiple_slots.num_slots() > 0 { let current_bucket = &mut self.data[bucket_ix as usize]; @@ -351,7 +352,7 @@ impl<'b, T: Clone + Copy + 'static> Bucket { if let Some((elem, elem_ix)) = self.find_index_entry(key) { let multiple_slots = elem.get_multiple_slots_mut(&mut self.index); if multiple_slots.num_slots() > 0 { - let ix = elem.data_bucket_ix(&self.index) as usize; + let ix = multiple_slots.data_bucket_ix() as usize; let data_bucket = &self.data[ix]; let loc = elem.data_loc(&self.index, data_bucket); let data_bucket = &mut self.data[ix]; diff --git a/bucket_map/src/index_entry.rs b/bucket_map/src/index_entry.rs index 072c67ec1..b0b485d0d 100644 --- a/bucket_map/src/index_entry.rs +++ b/bucket_map/src/index_entry.rs @@ -115,6 +115,24 @@ impl MultipleSlots { pub(crate) fn set_num_slots(&mut self, num_slots: Slot) { self.num_slots = num_slots; } + + pub(crate) fn data_bucket_ix(&self) -> u64 { + Self::data_bucket_from_num_slots(self.num_slots()) + } + + /// return closest bucket index fit for the slot slice. + /// Since bucket size is 2^index, the return value is + /// min index, such that 2^index >= num_slots + /// index = ceiling(log2(num_slots)) + /// special case, when slot slice empty, return 0th index. + pub(crate) fn data_bucket_from_num_slots(num_slots: Slot) -> u64 { + // Compute the ceiling of log2 for integer + if num_slots == 0 { + 0 + } else { + (Slot::BITS - (num_slots - 1).leading_zeros()) as u64 + } + } } /// Pack the storage offset and capacity-when-crated-pow2 fields into a single u64 @@ -126,22 +144,6 @@ struct PackedStorage { offset: B56, } -impl IndexEntry { - /// return closest bucket index fit for the slot slice. - /// Since bucket size is 2^index, the return value is - /// min index, such that 2^index >= num_slots - /// index = ceiling(log2(num_slots)) - /// special case, when slot slice empty, return 0th index. - pub fn data_bucket_from_num_slots(num_slots: Slot) -> u64 { - // Compute the ceiling of log2 for integer - if num_slots == 0 { - 0 - } else { - (Slot::BITS - (num_slots - 1).leading_zeros()) as u64 - } - } -} - impl IndexEntryPlaceInBucket { pub fn init(&self, index_bucket: &mut BucketStorage>, pubkey: &Pubkey) { let index_entry = index_bucket.get_mut::>(self.ix); @@ -150,10 +152,22 @@ impl IndexEntryPlaceInBucket { index_entry.multiple_slots = MultipleSlots::default(); } - pub fn data_bucket_ix(&self, index_bucket: &BucketStorage>) -> u64 { - IndexEntry::::data_bucket_from_num_slots( - self.get_multiple_slots(index_bucket).num_slots(), - ) + pub fn set_storage_capacity_when_created_pow2( + &self, + index_bucket: &mut BucketStorage>, + storage_capacity_when_created_pow2: u8, + ) { + self.get_multiple_slots_mut(index_bucket) + .set_storage_capacity_when_created_pow2(storage_capacity_when_created_pow2); + } + + pub fn set_storage_offset( + &self, + index_bucket: &mut BucketStorage>, + storage_offset: u64, + ) { + self.get_multiple_slots_mut(index_bucket) + .set_storage_offset(storage_offset); } pub(crate) fn get_multiple_slots<'a>( @@ -197,7 +211,7 @@ impl IndexEntryPlaceInBucket { let multiple_slots = self.get_multiple_slots(index_bucket); let num_slots = multiple_slots.num_slots(); let slice = if num_slots > 0 { - let data_bucket_ix = self.data_bucket_ix(index_bucket); + let data_bucket_ix = multiple_slots.data_bucket_ix(); let data_bucket = &data_buckets[data_bucket_ix as usize]; let loc = self.data_loc(index_bucket, data_bucket); assert!(!data_bucket.is_free(loc)); @@ -311,20 +325,20 @@ mod tests { fn test_data_bucket_from_num_slots() { for n in 0..512 { assert_eq!( - IndexEntry::::data_bucket_from_num_slots(n), + MultipleSlots::data_bucket_from_num_slots(n), (n as f64).log2().ceil() as u64 ); } assert_eq!( - IndexEntry::::data_bucket_from_num_slots(u32::MAX as u64), + MultipleSlots::data_bucket_from_num_slots(u32::MAX as u64), 32 ); assert_eq!( - IndexEntry::::data_bucket_from_num_slots(u32::MAX as u64 + 1), + MultipleSlots::data_bucket_from_num_slots(u32::MAX as u64 + 1), 32 ); assert_eq!( - IndexEntry::::data_bucket_from_num_slots(u32::MAX as u64 + 2), + MultipleSlots::data_bucket_from_num_slots(u32::MAX as u64 + 2), 33 ); }