Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move data_bucket_ix() method to MultipleSlots #30992

Merged
merged 1 commit into from
Mar 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions bucket_map/src/bucket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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)));
Expand All @@ -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];
Expand Down Expand Up @@ -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];
Expand Down
54 changes: 34 additions & 20 deletions bucket_map/src/index_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,24 +115,17 @@ impl MultipleSlots {
pub(crate) fn set_num_slots(&mut self, num_slots: Slot) {
self.num_slots = num_slots;
}
}

/// Pack the storage offset and capacity-when-crated-pow2 fields into a single u64
#[bitfield(bits = 64)]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
struct PackedStorage {
capacity_when_created_pow2: B8,
offset: B56,
}
pub(crate) fn data_bucket_ix(&self) -> u64 {
Self::data_bucket_from_num_slots(self.num_slots())
}

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 {
pub(crate) fn data_bucket_from_num_slots(num_slots: Slot) -> u64 {
// Compute the ceiling of log2 for integer
if num_slots == 0 {
0
Expand All @@ -142,6 +135,15 @@ impl<T> IndexEntry<T> {
}
}

/// Pack the storage offset and capacity-when-crated-pow2 fields into a single u64
#[bitfield(bits = 64)]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
struct PackedStorage {
capacity_when_created_pow2: B8,
offset: B56,
}

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);
Expand All @@ -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>(
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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
);
}
Expand Down