From c3db8a471fdacee790330b9024748069bbb62184 Mon Sep 17 00:00:00 2001 From: dmakarov Date: Wed, 23 Oct 2024 15:35:53 -0400 Subject: [PATCH] Increase the maximum of ancient slots allowed to be not combined (#3205) * Increase the maximum of ancient slots allowed to be not combined * OFFSET * Offset * Fix * Fix * Roots * Comment --- accounts-db/src/accounts_db.rs | 55 ++++++++++++++++++-------- accounts-db/src/ancient_append_vecs.rs | 6 ++- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/accounts-db/src/accounts_db.rs b/accounts-db/src/accounts_db.rs index 63a0e3c4ad0729..d7f1d91f0b7468 100644 --- a/accounts-db/src/accounts_db.rs +++ b/accounts-db/src/accounts_db.rs @@ -145,6 +145,10 @@ const SHRINK_COLLECT_CHUNK_SIZE: usize = 50; /// candidates for shrinking. const SHRINK_INSERT_ANCIENT_THRESHOLD: usize = 10; +/// Default value for the number of ancient storages the ancient slot +/// combining should converge to. +pub const MAX_ANCIENT_SLOTS_DEFAULT: usize = 100_000; + #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub enum CreateAncientStorage { /// ancient storages are created by appending @@ -592,9 +596,24 @@ pub struct AccountsAddRootTiming { pub store_us: u64, } -/// if negative, this many accounts older than # slots in epoch are still treated as modern (ie. non-ancient). -/// Slots older than # slots in epoch - this # are then treated as ancient and subject to packing. -const ANCIENT_APPEND_VEC_DEFAULT_OFFSET: Option = Some(-10_000); +/// Slots older the "number of slots in an epoch minus this number" +/// than max root are treated as ancient and subject to packing. +/// | older |<- slots in an epoch ->| max root +/// | older |<- offset ->| | +/// | ancient | modern | +/// +/// If this is negative, this many slots older than the number of +/// slots in epoch are still treated as modern (ie. non-ancient). +/// | older |<- abs(offset) ->|<- slots in an epoch ->| max root +/// | ancient | modern | +/// +/// Note that another constant MAX_ANCIENT_SLOTS_DEFAULT sets a +/// threshold for combining ancient storages so that their overall +/// number is under a certain limit, whereas this constant establishes +/// the distance from the max root slot beyond which storages holding +/// the account data for the slots are considered ancient by the +/// shrinking algorithm. +const ANCIENT_APPEND_VEC_DEFAULT_OFFSET: Option = Some(100_000); #[derive(Debug, Default, Clone)] pub struct AccountsDbConfig { @@ -15201,10 +15220,9 @@ pub mod tests { let slots_per_epoch = config.epoch_schedule.slots_per_epoch; assert_ne!(slot, 0); let offset = 10; - // no ancient append vecs, so always 0 assert_eq!( db.get_oldest_non_ancient_slot_for_hash_calc_scan(slots_per_epoch + offset, &config), - expected(0) + expected(db.ancient_append_vec_offset.unwrap() as u64 + offset + 1) ); // ancient append vecs enabled (but at 0 offset), so can be non-zero db.ancient_append_vec_offset = Some(0); @@ -15929,52 +15947,55 @@ pub mod tests { assert!(db .get_sorted_potential_ancient_slots(oldest_non_ancient_slot) .is_empty()); - let root0 = 0; - db.add_root(root0); - let root1 = 1; + let root1 = MAX_ANCIENT_SLOTS_DEFAULT as u64 + ancient_append_vec_offset as u64 + 1; db.add_root(root1); + let root2 = root1 + 1; + db.add_root(root2); let oldest_non_ancient_slot = db.get_oldest_non_ancient_slot(&epoch_schedule); assert!(db .get_sorted_potential_ancient_slots(oldest_non_ancient_slot) .is_empty()); let completed_slot = epoch_schedule.slots_per_epoch; - db.accounts_index.add_root(completed_slot); + db.accounts_index.add_root(AccountsDb::apply_offset_to_slot( + completed_slot, + ancient_append_vec_offset, + )); let oldest_non_ancient_slot = db.get_oldest_non_ancient_slot(&epoch_schedule); // get_sorted_potential_ancient_slots uses 'less than' as opposed to 'less or equal' // so, we need to get more than an epoch away to get the first valid root assert!(db .get_sorted_potential_ancient_slots(oldest_non_ancient_slot) .is_empty()); - let completed_slot = epoch_schedule.slots_per_epoch + root0; + let completed_slot = epoch_schedule.slots_per_epoch + root1; db.accounts_index.add_root(AccountsDb::apply_offset_to_slot( completed_slot, - -ancient_append_vec_offset, + ancient_append_vec_offset, )); let oldest_non_ancient_slot = db.get_oldest_non_ancient_slot(&epoch_schedule); assert_eq!( db.get_sorted_potential_ancient_slots(oldest_non_ancient_slot), - vec![root0] + vec![root1, root2] ); - let completed_slot = epoch_schedule.slots_per_epoch + root1; + let completed_slot = epoch_schedule.slots_per_epoch + root2; db.accounts_index.add_root(AccountsDb::apply_offset_to_slot( completed_slot, - -ancient_append_vec_offset, + ancient_append_vec_offset, )); let oldest_non_ancient_slot = db.get_oldest_non_ancient_slot(&epoch_schedule); assert_eq!( db.get_sorted_potential_ancient_slots(oldest_non_ancient_slot), - vec![root0, root1] + vec![root1, root2] ); db.accounts_index .roots_tracker .write() .unwrap() .alive_roots - .remove(&root0); + .remove(&root1); let oldest_non_ancient_slot = db.get_oldest_non_ancient_slot(&epoch_schedule); assert_eq!( db.get_sorted_potential_ancient_slots(oldest_non_ancient_slot), - vec![root1] + vec![root2] ); }); diff --git a/accounts-db/src/ancient_append_vecs.rs b/accounts-db/src/ancient_append_vecs.rs index 57d9b0be84dfc5..1a24b457aef5c3 100644 --- a/accounts-db/src/ancient_append_vecs.rs +++ b/accounts-db/src/ancient_append_vecs.rs @@ -11,6 +11,7 @@ use { stats::{ShrinkAncientStats, ShrinkStatsSub}, AccountFromStorage, AccountStorageEntry, AccountsDb, AliveAccounts, GetUniqueAccountsResult, ShrinkCollect, ShrinkCollectAliveSeparatedByRefs, + MAX_ANCIENT_SLOTS_DEFAULT, }, accounts_file::AccountsFile, active_stats::ActiveStatItem, @@ -343,8 +344,9 @@ impl AccountsDb { can_randomly_shrink: bool, ) { let tuning = PackedAncientStorageTuning { - // only allow 10k slots old enough to be ancient - max_ancient_slots: 10_000, + // Slots old enough to be ancient. Setting this parameter + // to 100k makes ancient storages to be approx 5M. + max_ancient_slots: MAX_ANCIENT_SLOTS_DEFAULT, // Don't re-pack anything just to shrink. // shrink_candidate_slots will handle these old storages. percent_of_alive_shrunk_data: 0,