Move `data_bucket_ix()` method to `MultipleSlots` (#30992)
move data_bucket_ix to MultipleSlots
This commit is contained in:
parent
b5afcbb72f
commit
89f7d4ab9a
|
@ -4,7 +4,9 @@ use {
|
||||||
bucket_map::BucketMapError,
|
bucket_map::BucketMapError,
|
||||||
bucket_stats::BucketMapStats,
|
bucket_stats::BucketMapStats,
|
||||||
bucket_storage::{BucketOccupied, BucketStorage, DEFAULT_CAPACITY_POW2},
|
bucket_storage::{BucketOccupied, BucketStorage, DEFAULT_CAPACITY_POW2},
|
||||||
index_entry::{DataBucket, IndexBucket, IndexEntry, IndexEntryPlaceInBucket},
|
index_entry::{
|
||||||
|
DataBucket, IndexBucket, IndexEntry, IndexEntryPlaceInBucket, MultipleSlots,
|
||||||
|
},
|
||||||
MaxSearch, RefCount,
|
MaxSearch, RefCount,
|
||||||
},
|
},
|
||||||
rand::{thread_rng, Rng},
|
rand::{thread_rng, Rng},
|
||||||
|
@ -265,7 +267,7 @@ impl<'b, T: Clone + Copy + 'static> Bucket<T> {
|
||||||
data_len: usize,
|
data_len: usize,
|
||||||
ref_count: RefCount,
|
ref_count: RefCount,
|
||||||
) -> Result<(), BucketMapError> {
|
) -> 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() {
|
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
|
// 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)));
|
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);
|
elem.set_ref_count(&mut self.index, ref_count);
|
||||||
let current_multiple_slots = elem.get_multiple_slots(&self.index);
|
let current_multiple_slots = elem.get_multiple_slots(&self.index);
|
||||||
let bucket_ix =
|
let bucket_ix = current_multiple_slots.data_bucket_ix();
|
||||||
IndexEntry::<T>::data_bucket_from_num_slots(current_multiple_slots.num_slots());
|
|
||||||
let num_slots = data_len as u64;
|
let num_slots = data_len as u64;
|
||||||
if best_fit_bucket == bucket_ix && current_multiple_slots.num_slots() > 0 {
|
if best_fit_bucket == bucket_ix && current_multiple_slots.num_slots() > 0 {
|
||||||
let current_bucket = &mut self.data[bucket_ix as usize];
|
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) {
|
if let Some((elem, elem_ix)) = self.find_index_entry(key) {
|
||||||
let multiple_slots = elem.get_multiple_slots_mut(&mut self.index);
|
let multiple_slots = elem.get_multiple_slots_mut(&mut self.index);
|
||||||
if multiple_slots.num_slots() > 0 {
|
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 data_bucket = &self.data[ix];
|
||||||
let loc = elem.data_loc(&self.index, data_bucket);
|
let loc = elem.data_loc(&self.index, data_bucket);
|
||||||
let data_bucket = &mut self.data[ix];
|
let data_bucket = &mut self.data[ix];
|
||||||
|
|
|
@ -115,6 +115,24 @@ impl MultipleSlots {
|
||||||
pub(crate) fn set_num_slots(&mut self, num_slots: Slot) {
|
pub(crate) fn set_num_slots(&mut self, num_slots: Slot) {
|
||||||
self.num_slots = num_slots;
|
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
|
/// Pack the storage offset and capacity-when-crated-pow2 fields into a single u64
|
||||||
|
@ -126,22 +144,6 @@ struct PackedStorage {
|
||||||
offset: B56,
|
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> {
|
impl<T> IndexEntryPlaceInBucket<T> {
|
||||||
pub fn init(&self, index_bucket: &mut BucketStorage<IndexBucket<T>>, pubkey: &Pubkey) {
|
pub fn init(&self, index_bucket: &mut BucketStorage<IndexBucket<T>>, pubkey: &Pubkey) {
|
||||||
let index_entry = index_bucket.get_mut::<IndexEntry<T>>(self.ix);
|
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();
|
index_entry.multiple_slots = MultipleSlots::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn data_bucket_ix(&self, index_bucket: &BucketStorage<IndexBucket<T>>) -> u64 {
|
pub fn set_storage_capacity_when_created_pow2(
|
||||||
IndexEntry::<T>::data_bucket_from_num_slots(
|
&self,
|
||||||
self.get_multiple_slots(index_bucket).num_slots(),
|
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>(
|
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 multiple_slots = self.get_multiple_slots(index_bucket);
|
||||||
let num_slots = multiple_slots.num_slots();
|
let num_slots = multiple_slots.num_slots();
|
||||||
let slice = if num_slots > 0 {
|
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 data_bucket = &data_buckets[data_bucket_ix as usize];
|
||||||
let loc = self.data_loc(index_bucket, data_bucket);
|
let loc = self.data_loc(index_bucket, data_bucket);
|
||||||
assert!(!data_bucket.is_free(loc));
|
assert!(!data_bucket.is_free(loc));
|
||||||
|
@ -311,20 +325,20 @@ mod tests {
|
||||||
fn test_data_bucket_from_num_slots() {
|
fn test_data_bucket_from_num_slots() {
|
||||||
for n in 0..512 {
|
for n in 0..512 {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
IndexEntry::<u64>::data_bucket_from_num_slots(n),
|
MultipleSlots::data_bucket_from_num_slots(n),
|
||||||
(n as f64).log2().ceil() as u64
|
(n as f64).log2().ceil() as u64
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
IndexEntry::<u64>::data_bucket_from_num_slots(u32::MAX as u64),
|
MultipleSlots::data_bucket_from_num_slots(u32::MAX as u64),
|
||||||
32
|
32
|
||||||
);
|
);
|
||||||
assert_eq!(
|
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
|
32
|
||||||
);
|
);
|
||||||
assert_eq!(
|
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
|
33
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue