diff --git a/accounts-db/src/accounts_db.rs b/accounts-db/src/accounts_db.rs index d528c4a3c6b47d..8fe9abb398aafe 100644 --- a/accounts-db/src/accounts_db.rs +++ b/accounts-db/src/accounts_db.rs @@ -2042,6 +2042,7 @@ pub struct ShrinkStats { accounts_loaded: AtomicU64, purged_zero_lamports: AtomicU64, accounts_not_found_in_index: AtomicU64, + adding_slots_to_clean: AtomicU64, num_ancient_slots_shrunk: AtomicU64, } @@ -2166,6 +2167,11 @@ impl ShrinkStats { self.accounts_not_found_in_index.swap(0, Ordering::Relaxed), i64 ), + ( + "adding_slots_to_clean", + self.adding_slots_to_clean.swap(0, Ordering::Relaxed), + i64 + ), ); } } @@ -2399,6 +2405,13 @@ impl ShrinkAncientStats { .swap(0, Ordering::Relaxed), i64 ), + ( + "adding_slots_to_clean", + self.shrink_stats + .adding_slots_to_clean + .swap(0, Ordering::Relaxed), + i64 + ), ); } } @@ -3440,7 +3453,7 @@ impl AccountsDb { }, None, false, - ScanFilter::All, + self.scan_filter_for_shrinking, ); }); found_not_zero_accum.fetch_add(found_not_zero, Ordering::Relaxed); @@ -3975,6 +3988,7 @@ impl AccountsDb { let mut alive = 0; let mut dead = 0; let mut index = 0; + let mut adding_slots_to_clean = 0; let mut index_scan_returned_some_count = 0; let mut index_scan_returned_none_count = 0; let mut all_are_zero_lamports = true; @@ -4019,6 +4033,18 @@ impl AccountsDb { // rewriting the storage entries. pubkeys_to_unref.push(pubkey); dead += 1; + + // If we are marking something dead, and the only remaining alive account is zero lamport, then make that zero lamport slot ready to be cleaned. + // If that slot happens to only contain zero lamport accounts, the whole slot will go away + if slot_list.len() == 1 // should we also check for ref counts here? + && slot_list + .iter() + .all(|(_slot, acct_info)| acct_info.is_zero_lamport()) + { + adding_slots_to_clean += 1; + self.accounts_index + .add_uncleaned_roots(slot_list.iter().map(|(slot, _)| *slot)); + } } else { do_populate_accounts_for_shrink(ref_count, slot_list); } @@ -4049,6 +4075,9 @@ impl AccountsDb { .fetch_add(index_scan_returned_none_count, Ordering::Relaxed); stats.alive_accounts.fetch_add(alive, Ordering::Relaxed); stats.dead_accounts.fetch_add(dead, Ordering::Relaxed); + stats + .adding_slots_to_clean + .fetch_add(adding_slots_to_clean, Ordering::Relaxed); LoadAccountsIndexForShrink { alive_accounts, diff --git a/accounts-db/src/accounts_index/in_mem_accounts_index.rs b/accounts-db/src/accounts_index/in_mem_accounts_index.rs index 5566ab4420cfd8..e007bf515c8688 100644 --- a/accounts-db/src/accounts_index/in_mem_accounts_index.rs +++ b/accounts-db/src/accounts_index/in_mem_accounts_index.rs @@ -1013,8 +1013,10 @@ impl + Into> InMemAccountsIndex 1 slot lists in mem. They will be cleaned or shrunk soon. } else { - // keep items with slot lists that contained cached items - let evict = !slot_list.iter().any(|(_, info)| info.is_cached()); + // keep items with slot lists that contained cached items or zero lamports + let evict = !slot_list + .iter() + .any(|(_, info)| info.is_cached() || info.is_zero_lamport()); if !evict && update_stats { Self::update_stat(&self.stats().held_in_mem.slot_list_cached, 1); }