Skip to content

Commit

Permalink
Move ideal_storage_size calculation before it is used (anza-xyz#3250)
Browse files Browse the repository at this point in the history
* Move ideal_storage_size calculation before it is used

* Add test
  • Loading branch information
dmakarov authored Oct 29, 2024
1 parent 838c195 commit 91d0a5e
Showing 1 changed file with 41 additions and 15 deletions.
56 changes: 41 additions & 15 deletions accounts-db/src/ancient_append_vecs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,14 +416,8 @@ impl AccountsDb {
self.shrink_ancient_stats
.slots_considered
.fetch_add(sorted_slots.len() as u64, Ordering::Relaxed);
let mut ancient_slot_infos = self.collect_sort_filter_ancient_slots(sorted_slots, &tuning);
// ideal storage size is total alive bytes of ancient storages
// divided by half of max ancient slots
tuning.ideal_storage_size = NonZeroU64::new(
(ancient_slot_infos.total_alive_bytes.0 * 2 / tuning.max_ancient_slots.max(1) as u64)
.max(MINIMAL_IDEAL_STORAGE_SIZE),
)
.unwrap();
let mut ancient_slot_infos =
self.collect_sort_filter_ancient_slots(sorted_slots, &mut tuning);
self.shrink_ancient_stats
.ideal_storage_size
.store(tuning.ideal_storage_size.into(), Ordering::Relaxed);
Expand Down Expand Up @@ -528,9 +522,16 @@ impl AccountsDb {
fn collect_sort_filter_ancient_slots(
&self,
slots: Vec<Slot>,
tuning: &PackedAncientStorageTuning,
tuning: &mut PackedAncientStorageTuning,
) -> AncientSlotInfos {
let mut ancient_slot_infos = self.calc_ancient_slot_info(slots, tuning);
// ideal storage size is total alive bytes of ancient storages
// divided by half of max ancient slots
tuning.ideal_storage_size = NonZeroU64::new(
(ancient_slot_infos.total_alive_bytes.0 * 2 / tuning.max_ancient_slots.max(1) as u64)
.max(MINIMAL_IDEAL_STORAGE_SIZE),
)
.unwrap();

ancient_slot_infos.filter_ancient_slots(tuning, &self.shrink_ancient_stats);
ancient_slot_infos
Expand Down Expand Up @@ -2584,7 +2585,7 @@ pub mod tests {
let alive_bytes_expected = storage.alive_bytes();
let high_slot = false;
let is_candidate_for_shrink = db.is_candidate_for_shrink(&storage);
let tuning = PackedAncientStorageTuning {
let mut tuning = PackedAncientStorageTuning {
percent_of_alive_shrunk_data: 100,
max_ancient_slots: 0,
// irrelevant for what this test is trying to test, but necessary to avoid minimums
Expand All @@ -2608,7 +2609,7 @@ pub mod tests {
infos = db.calc_ancient_slot_info(vec![slot1], &tuning);
}
TestCollectInfo::CollectSortFilterInfo => {
infos = db.collect_sort_filter_ancient_slots(vec![slot1], &tuning);
infos = db.collect_sort_filter_ancient_slots(vec![slot1], &mut tuning);
}
}
assert_eq!(infos.all_infos.len(), 1, "{method:?}");
Expand Down Expand Up @@ -2794,7 +2795,7 @@ pub mod tests {
continue; // unsupportable
}
TestCollectInfo::CollectSortFilterInfo => {
let tuning = PackedAncientStorageTuning {
let mut tuning = PackedAncientStorageTuning {
percent_of_alive_shrunk_data: 100,
max_ancient_slots: 0,
// irrelevant
Expand All @@ -2805,7 +2806,7 @@ pub mod tests {
can_randomly_shrink,
..default_tuning()
};
db.collect_sort_filter_ancient_slots(slot_vec.clone(), &tuning)
db.collect_sort_filter_ancient_slots(slot_vec.clone(), &mut tuning)
}
};
assert_eq!(infos.all_infos.len(), 1, "method: {method:?}");
Expand Down Expand Up @@ -3168,7 +3169,7 @@ pub mod tests {
#[test]
fn test_calc_ancient_slot_info_one_shrink_one_not() {
let can_randomly_shrink = false;
let tuning = PackedAncientStorageTuning {
let mut tuning = PackedAncientStorageTuning {
percent_of_alive_shrunk_data: 100,
max_ancient_slots: 0,
// irrelevant for what this test is trying to test, but necessary to avoid minimums
Expand Down Expand Up @@ -3220,7 +3221,7 @@ pub mod tests {
}
TestCollectInfo::CollectSortFilterInfo => {
// note this can sort infos.all_infos
db.collect_sort_filter_ancient_slots(slot_vec.clone(), &tuning)
db.collect_sort_filter_ancient_slots(slot_vec.clone(), &mut tuning)
}
};

Expand Down Expand Up @@ -3985,6 +3986,31 @@ pub mod tests {
}
}

/// The purpose of this test is to ensure the correct control flow
/// of calculating and using the value of the tuning parameter
/// `ideal_storage_size`.
#[test]
fn test_ideal_storage_size_updated_before_used() {
let mut tuning = PackedAncientStorageTuning {
percent_of_alive_shrunk_data: 100,
max_ancient_slots: 100,
..default_tuning()
};
let data_size = 1_000_000;
let num_slots = tuning.max_ancient_slots;
let (db, slot1) =
create_db_with_storages_and_index(true /*alive*/, num_slots, Some(data_size));
let non_ancient_slot = slot1 + (2 * tuning.max_ancient_slots) as u64;
create_storages_and_update_index(&db, None, non_ancient_slot, 1, true, Some(data_size));
let mut slot_vec = (slot1..(slot1 + num_slots as Slot)).collect::<Vec<_>>();
slot_vec.push(non_ancient_slot);
let infos = db.collect_sort_filter_ancient_slots(slot_vec.clone(), &mut tuning);
let ideal_storage_size = tuning.ideal_storage_size.get();
let max_resulting_storages = tuning.max_resulting_storages.get();
let expected_all_infos_len = max_resulting_storages * ideal_storage_size / data_size - 1;
assert_eq!(infos.all_infos.len(), expected_all_infos_len as usize);
}

#[test_case(0, 1 => 0)]
#[test_case(1, 1 => 1)]
#[test_case(2, 1 => 2)]
Expand Down

0 comments on commit 91d0a5e

Please sign in to comment.