Move `data_bucket_ix()` method to `MultipleSlots` (#30992)

move data_bucket_ix to MultipleSlots
This commit is contained in:
Jeff Washington (jwash) 2023-03-30 15:20:10 -05:00 committed by GitHub
parent b5afcbb72f
commit 89f7d4ab9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 30 deletions

View File

@ -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<T> {
data_len: usize,
ref_count: RefCount,
) -> Result<(), BucketMapError> {
let best_fit_bucket = IndexEntry::<T>::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<T> {
elem.set_ref_count(&mut self.index, ref_count);
let current_multiple_slots = elem.get_multiple_slots(&self.index);
let bucket_ix =
IndexEntry::<T>::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<T> {
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];

View File

@ -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<T> IndexEntry<T> {
/// 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<T> IndexEntryPlaceInBucket<T> {
pub fn init(&self, index_bucket: &mut BucketStorage<IndexBucket<T>>, pubkey: &Pubkey) {
let index_entry = index_bucket.get_mut::<IndexEntry<T>>(self.ix);
@ -150,10 +152,22 @@ impl<T> IndexEntryPlaceInBucket<T> {
index_entry.multiple_slots = MultipleSlots::default();
}
pub fn data_bucket_ix(&self, index_bucket: &BucketStorage<IndexBucket<T>>) -> u64 {
IndexEntry::<T>::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<IndexBucket<T>>,
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<IndexBucket<T>>,
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<T> IndexEntryPlaceInBucket<T> {
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::<u64>::data_bucket_from_num_slots(n),
MultipleSlots::data_bucket_from_num_slots(n),
(n as f64).log2().ceil() as u64
);
}
assert_eq!(
IndexEntry::<u64>::data_bucket_from_num_slots(u32::MAX as u64),
MultipleSlots::data_bucket_from_num_slots(u32::MAX as u64),
32
);
assert_eq!(
IndexEntry::<u64>::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::<u64>::data_bucket_from_num_slots(u32::MAX as u64 + 2),
MultipleSlots::data_bucket_from_num_slots(u32::MAX as u64 + 2),
33
);
}