root -> alive_root (#24062)

This commit is contained in:
Jeff Washington (jwash) 2022-04-02 12:00:52 -05:00 committed by GitHub
parent ffa4cafe1c
commit 3ca4fffa78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 53 deletions

View File

@ -2950,8 +2950,8 @@ impl AccountsDb {
self.storage.all_slots()
}
fn all_root_slots_in_index(&self) -> Vec<Slot> {
self.accounts_index.all_roots()
fn all_alive_roots_in_index(&self) -> Vec<Slot> {
self.accounts_index.all_alive_roots()
}
/// Given the input `ShrinkCandidates`, this function sorts the stores by their alive ratio
@ -4296,7 +4296,7 @@ impl AccountsDb {
// Also note roots are never removed via `remove_unrooted_slot()`, so
// it's safe to filter them out here as they won't need deletion from
// self.accounts_index.removed_bank_ids in `purge_slots_from_cache_and_store()`.
.filter(|slot| !self.accounts_index.is_root(**slot));
.filter(|slot| !self.accounts_index.is_alive_root(**slot));
safety_checks_elapsed.stop();
self.external_purge_slots_stats
.safety_checks_elapsed
@ -5437,7 +5437,7 @@ impl AccountsDb {
if let Some(slot_cache) = self.accounts_cache.slot_cache(slot) {
if valid_slot
|| ancestors.contains_key(&slot)
|| self.accounts_index.is_root(slot)
|| self.accounts_index.is_alive_root(slot)
{
let keys = slot_cache.get_all_pubkeys();
for key in keys {
@ -5510,7 +5510,7 @@ impl AccountsDb {
collect_time.stop();
let mut sort_time = Measure::start("sort_storages");
let min_root = self.accounts_index.min_root();
let min_root = self.accounts_index.min_alive_root();
let storages = SortedStorages::new_with_slots(
combined_maps.iter().zip(slots.into_iter()),
min_root,
@ -6630,7 +6630,7 @@ impl AccountsDb {
if *slot <= snapshot_slot
&& snapshot_base_slot
.map_or(true, |snapshot_base_slot| *slot > snapshot_base_slot)
&& (self.accounts_index.is_root(*slot)
&& (self.accounts_index.is_alive_root(*slot)
|| ancestors
.map(|ancestors| ancestors.contains_key(slot))
.unwrap_or_default())
@ -7274,10 +7274,10 @@ impl AccountsDb {
}
fn print_index(&self, label: &str) {
let mut roots: Vec<_> = self.accounts_index.all_roots();
let mut alive_roots: Vec<_> = self.accounts_index.all_alive_roots();
#[allow(clippy::stable_sort_primitive)]
roots.sort();
info!("{}: accounts_index roots: {:?}", label, roots,);
alive_roots.sort();
info!("{}: accounts_index alive_roots: {:?}", label, alive_roots,);
let full_pubkey_range = Pubkey::new(&[0; 32])..=Pubkey::new(&[0xff; 32]);
self.accounts_index.account_maps.iter().for_each(|map| {
@ -7449,7 +7449,7 @@ impl AccountsDb {
let mut shrunken_account_total = 0;
let mut shrunk_slot_count = 0;
let start = Instant::now();
let num_roots = self.accounts_index.num_roots();
let num_roots = self.accounts_index.num_alive_roots();
loop {
if let Some(slot) = self.do_next_shrink_slot_v1(candidates) {
shrunken_account_total += self.do_shrink_stale_slot_v1(slot);
@ -7480,7 +7480,7 @@ impl AccountsDb {
if next.is_some() {
next
} else {
let mut new_all_slots = self.all_root_slots_in_index();
let mut new_all_slots = self.all_alive_roots_in_index();
let next = new_all_slots.pop();
// refresh candidates for later calls!
**candidates = new_all_slots;

View File

@ -400,11 +400,11 @@ impl<T: IndexValue> PreAllocatedAccountMapEntry<T> {
#[derive(Debug)]
pub struct RootsTracker {
/// current set of roots active in approx. the current epoch
pub(crate) roots: RollingBitField,
/// current set of roots alive in approx. the current epoch
pub(crate) alive_roots: RollingBitField,
/// Set of roots approx. within the current epoch that are roots now or were roots at one point in time.
/// A root could remain here if all entries in the append vec at that root are cleaned/shrunk and there are no
/// more entries that slot. 'roots' will no longer contain such roots.
/// more entries that slot. 'alive_roots' will no longer contain such roots.
pub(crate) roots_original: RollingBitField,
uncleaned_roots: HashSet<Slot>,
previous_uncleaned_roots: HashSet<Slot>,
@ -422,15 +422,15 @@ impl Default for RootsTracker {
impl RootsTracker {
pub fn new(max_width: u64) -> Self {
Self {
roots: RollingBitField::new(max_width),
alive_roots: RollingBitField::new(max_width),
roots_original: RollingBitField::new(max_width),
uncleaned_roots: HashSet::new(),
previous_uncleaned_roots: HashSet::new(),
}
}
pub fn min_root(&self) -> Option<Slot> {
self.roots.min()
pub fn min_alive_root(&self) -> Option<Slot> {
self.alive_roots.min()
}
}
@ -1157,7 +1157,7 @@ impl<T: IndexValue> AccountsIndex<T> {
pub fn get_rooted_entries(&self, slice: SlotSlice<T>, max: Option<Slot>) -> SlotList<T> {
let max = max.unwrap_or(Slot::MAX);
let lock = &self.roots_tracker.read().unwrap().roots;
let lock = &self.roots_tracker.read().unwrap().alive_roots;
slice
.iter()
.filter(|(slot, _)| *slot <= max && lock.contains(slot))
@ -1240,7 +1240,7 @@ impl<T: IndexValue> AccountsIndex<T> {
Some(inner) => inner,
None => self.roots_tracker.read().unwrap(),
};
if lock.roots.contains(slot) {
if lock.alive_roots.contains(slot) {
rv = Some(i);
current_max = *slot;
}
@ -1341,7 +1341,7 @@ impl<T: IndexValue> AccountsIndex<T> {
// Get the maximum root <= `max_allowed_root` from the given `slice`
fn get_newest_root_in_slot_list(
roots: &RollingBitField,
alive_roots: &RollingBitField,
slice: SlotSlice<T>,
max_allowed_root: Option<Slot>,
) -> Slot {
@ -1352,7 +1352,7 @@ impl<T: IndexValue> AccountsIndex<T> {
continue;
}
}
if *f > max_root && roots.contains(f) {
if *f > max_root && alive_roots.contains(f) {
max_root = *f;
}
}
@ -1609,9 +1609,13 @@ impl<T: IndexValue> AccountsIndex<T> {
max_clean_root: Option<Slot>,
) {
let roots_tracker = &self.roots_tracker.read().unwrap();
let newest_root_in_slot_list =
Self::get_newest_root_in_slot_list(&roots_tracker.roots, slot_list, max_clean_root);
let max_clean_root = max_clean_root.unwrap_or_else(|| roots_tracker.roots.max_inclusive());
let newest_root_in_slot_list = Self::get_newest_root_in_slot_list(
&roots_tracker.alive_roots,
slot_list,
max_clean_root,
);
let max_clean_root =
max_clean_root.unwrap_or_else(|| roots_tracker.alive_roots.max_inclusive());
slot_list.retain(|(slot, value)| {
let should_purge =
@ -1671,7 +1675,7 @@ impl<T: IndexValue> AccountsIndex<T> {
let roots_tracker = self.roots_tracker.read().unwrap();
slots
.filter_map(|s| {
if roots_tracker.roots.contains(s) {
if roots_tracker.alive_roots.contains(s) {
Some(*s)
} else {
None
@ -1680,16 +1684,20 @@ impl<T: IndexValue> AccountsIndex<T> {
.collect()
}
pub fn is_root(&self, slot: Slot) -> bool {
self.roots_tracker.read().unwrap().roots.contains(&slot)
pub fn is_alive_root(&self, slot: Slot) -> bool {
self.roots_tracker
.read()
.unwrap()
.alive_roots
.contains(&slot)
}
pub fn add_root(&self, slot: Slot, caching_enabled: bool) {
let mut w_roots_tracker = self.roots_tracker.write().unwrap();
// `AccountsDb::flush_accounts_cache()` relies on roots being added in order
assert!(slot >= w_roots_tracker.roots.max_inclusive());
assert!(slot >= w_roots_tracker.alive_roots.max_inclusive());
// 'slot' is a root, so it is both 'root' and 'original'
w_roots_tracker.roots.insert(slot);
w_roots_tracker.alive_roots.insert(slot);
w_roots_tracker.roots_original.insert(slot);
// we delay cleaning until flushing!
if !caching_enabled {
@ -1706,7 +1714,11 @@ impl<T: IndexValue> AccountsIndex<T> {
}
pub fn max_root_inclusive(&self) -> Slot {
self.roots_tracker.read().unwrap().roots.max_inclusive()
self.roots_tracker
.read()
.unwrap()
.alive_roots
.max_inclusive()
}
/// return the lowest original root >= slot, including roots_original and ancestors
@ -1762,7 +1774,7 @@ impl<T: IndexValue> AccountsIndex<T> {
let removed_from_unclean_roots = w_roots_tracker.uncleaned_roots.remove(&slot);
let removed_from_previous_uncleaned_roots =
w_roots_tracker.previous_uncleaned_roots.remove(&slot);
if !w_roots_tracker.roots.remove(&slot) {
if !w_roots_tracker.alive_roots.remove(&slot) {
if removed_from_unclean_roots {
error!("clean_dead_slot-removed_from_unclean_roots: {}", slot);
inc_new_counter_error!("clean_dead_slot-removed_from_unclean_roots", 1, 1);
@ -1780,16 +1792,16 @@ impl<T: IndexValue> AccountsIndex<T> {
}
false
} else {
stats.roots_len = w_roots_tracker.roots.len();
stats.roots_len = w_roots_tracker.alive_roots.len();
stats.uncleaned_roots_len = w_roots_tracker.uncleaned_roots.len();
stats.previous_uncleaned_roots_len = w_roots_tracker.previous_uncleaned_roots.len();
stats.roots_range = w_roots_tracker.roots.range_width();
stats.roots_range = w_roots_tracker.alive_roots.range_width();
true
}
}
pub fn min_root(&self) -> Option<Slot> {
self.roots_tracker.read().unwrap().min_root()
pub fn min_alive_root(&self) -> Option<Slot> {
self.roots_tracker.read().unwrap().min_alive_root()
}
pub fn reset_uncleaned_roots(&self, max_clean_root: Option<Slot>) -> HashSet<Slot> {
@ -1833,18 +1845,18 @@ impl<T: IndexValue> AccountsIndex<T> {
.contains(&slot)
}
pub fn num_roots(&self) -> usize {
self.roots_tracker.read().unwrap().roots.len()
pub fn num_alive_roots(&self) -> usize {
self.roots_tracker.read().unwrap().alive_roots.len()
}
pub fn all_roots(&self) -> Vec<Slot> {
pub fn all_alive_roots(&self) -> Vec<Slot> {
let tracker = self.roots_tracker.read().unwrap();
tracker.roots.get_all()
tracker.alive_roots.get_all()
}
#[cfg(test)]
pub fn clear_roots(&self) {
self.roots_tracker.write().unwrap().roots.clear()
self.roots_tracker.write().unwrap().alive_roots.clear()
}
pub fn clone_uncleaned_roots(&self) -> HashSet<Slot> {
@ -1862,7 +1874,7 @@ impl<T: IndexValue> AccountsIndex<T> {
pub fn purge_roots(&self, pubkey: &Pubkey) -> (SlotList<T>, bool) {
self.slot_list_mut(pubkey, |slot_list| {
let reclaims = self.get_rooted_entries(slot_list, None);
slot_list.retain(|(slot, _)| !self.is_root(*slot));
slot_list.retain(|(slot, _)| !self.is_alive_root(*slot));
(reclaims, slot_list.is_empty())
})
.unwrap()
@ -2799,11 +2811,11 @@ pub mod tests {
}
#[test]
fn test_is_root() {
fn test_is_alive_root() {
let index = AccountsIndex::<bool>::default_for_tests();
assert!(!index.is_root(0));
assert!(!index.is_alive_root(0));
index.add_root(0, false);
assert!(index.is_root(0));
assert!(index.is_alive_root(0));
}
#[test]
@ -2834,8 +2846,8 @@ pub mod tests {
index.add_root(0, false);
index.add_root(1, false);
index.clean_dead_slot(0, &mut AccountsIndexRootsStats::default());
assert!(index.is_root(1));
assert!(!index.is_root(0));
assert!(index.is_alive_root(1));
assert!(!index.is_alive_root(0));
}
#[test]
@ -2845,8 +2857,8 @@ pub mod tests {
index.add_root(0, false);
index.add_root(1, false);
index.clean_dead_slot(1, &mut AccountsIndexRootsStats::default());
assert!(!index.is_root(1));
assert!(index.is_root(0));
assert!(!index.is_alive_root(1));
assert!(index.is_alive_root(0));
}
#[test]
@ -2867,7 +2879,7 @@ pub mod tests {
.len()
);
index.reset_uncleaned_roots(None);
assert_eq!(2, index.roots_tracker.read().unwrap().roots.len());
assert_eq!(2, index.roots_tracker.read().unwrap().alive_roots.len());
assert_eq!(0, index.roots_tracker.read().unwrap().uncleaned_roots.len());
assert_eq!(
2,
@ -2881,7 +2893,7 @@ pub mod tests {
index.add_root(2, false);
index.add_root(3, false);
assert_eq!(4, index.roots_tracker.read().unwrap().roots.len());
assert_eq!(4, index.roots_tracker.read().unwrap().alive_roots.len());
assert_eq!(2, index.roots_tracker.read().unwrap().uncleaned_roots.len());
assert_eq!(
2,
@ -2894,7 +2906,7 @@ pub mod tests {
);
index.clean_dead_slot(1, &mut AccountsIndexRootsStats::default());
assert_eq!(3, index.roots_tracker.read().unwrap().roots.len());
assert_eq!(3, index.roots_tracker.read().unwrap().alive_roots.len());
assert_eq!(2, index.roots_tracker.read().unwrap().uncleaned_roots.len());
assert_eq!(
1,
@ -2907,7 +2919,7 @@ pub mod tests {
);
index.clean_dead_slot(2, &mut AccountsIndexRootsStats::default());
assert_eq!(2, index.roots_tracker.read().unwrap().roots.len());
assert_eq!(2, index.roots_tracker.read().unwrap().alive_roots.len());
assert_eq!(1, index.roots_tracker.read().unwrap().uncleaned_roots.len());
assert_eq!(
1,

View File

@ -245,7 +245,7 @@ impl<'a> TypeContext<'a> for Context {
.roots_tracker
.read()
.unwrap()
.roots
.alive_roots
.get_all();
let prior_roots_with_hash = Vec::<(Slot, Hash)>::default();