diff --git a/bucket_map/src/bucket_map.rs b/bucket_map/src/bucket_map.rs index 0193642c408022..309eabf37d8494 100644 --- a/bucket_map/src/bucket_map.rs +++ b/bucket_map/src/bucket_map.rs @@ -365,7 +365,7 @@ mod tests { let v = (0..count) .map(|x| (x as usize, x as usize /*thread_rng().gen::()*/)) .collect::>(); - let rc = thread_rng().gen::(); + let rc = thread_rng().gen_range(0, RefCount::MAX >> 2); (v, rc) }; diff --git a/bucket_map/src/bucket_storage.rs b/bucket_map/src/bucket_storage.rs index 5f810378cbeea2..effda2cc97ab20 100644 --- a/bucket_map/src/bucket_storage.rs +++ b/bucket_map/src/bucket_storage.rs @@ -372,7 +372,7 @@ mod test { let mut storage = BucketStorage::>::new( Arc::new(paths), 1, - 1, + std::mem::size_of::>() as u64, 1, Arc::default(), Arc::default(), diff --git a/bucket_map/src/index_entry.rs b/bucket_map/src/index_entry.rs index 80dc68967fdfcf..34dd4ad827de01 100644 --- a/bucket_map/src/index_entry.rs +++ b/bucket_map/src/index_entry.rs @@ -66,15 +66,26 @@ pub struct IndexEntryPlaceInBucket { #[repr(C)] #[derive(Copy, Clone)] -// one instance of this per item in the index -// stored in the index bucket +/// one instance of this per item in the index +/// stored in the index bucket pub struct IndexEntry { - pub key: Pubkey, // can this be smaller if we have reduced the keys into buckets already? - ref_count: RefCount, // can this be smaller? Do we ever need more than 4B refcounts? + pub(crate) key: Pubkey, // can this be smaller if we have reduced the keys into buckets already? + packed_ref_count: PackedRefCount, multiple_slots: MultipleSlots, _phantom: PhantomData<&'static T>, } +/// hold a big `RefCount` while leaving room for extra bits to be used for things like 'Occupied' +#[bitfield(bits = 64)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] +struct PackedRefCount { + /// reserved for future use + unused: B2, + /// ref_count of this entry. We don't need any where near 62 bits for this value + ref_count: B62, +} + /// required fields when an index element references the data file #[repr(C)] #[derive(Debug, Default, Copy, Clone)] @@ -82,7 +93,7 @@ pub(crate) struct MultipleSlots { // if the bucket doubled, the index can be recomputed using storage_cap_and_offset.create_bucket_capacity_pow2 storage_cap_and_offset: PackedStorage, /// num elements in the slot list - num_slots: Slot, // can this be smaller? epoch size should ~ be the max len. this is the num elements in the slot list + num_slots: Slot, } impl MultipleSlots { @@ -154,7 +165,7 @@ impl IndexEntryPlaceInBucket { pub fn init(&self, index_bucket: &mut BucketStorage>, pubkey: &Pubkey) { let index_entry = index_bucket.get_mut::>(self.ix); index_entry.key = *pubkey; - index_entry.ref_count = 0; + index_entry.packed_ref_count.set_ref_count(0); index_entry.multiple_slots = MultipleSlots::default(); } @@ -194,7 +205,7 @@ impl IndexEntryPlaceInBucket { pub fn ref_count(&self, index_bucket: &BucketStorage>) -> RefCount { let index_entry = index_bucket.get::>(self.ix); - index_entry.ref_count + index_entry.packed_ref_count.ref_count() } pub fn read_value<'a>( @@ -235,7 +246,10 @@ impl IndexEntryPlaceInBucket { ref_count: RefCount, ) { let index_entry = index_bucket.get_mut::>(self.ix); - index_entry.ref_count = ref_count; + index_entry + .packed_ref_count + .set_ref_count_checked(ref_count) + .expect("ref count must fit into 62 bits!"); } } @@ -251,7 +265,7 @@ mod tests { pub fn new(key: Pubkey) -> Self { IndexEntry { key, - ref_count: 0, + packed_ref_count: PackedRefCount::default(), multiple_slots: MultipleSlots::default(), _phantom: PhantomData, }