Bank: Batch account stores in collect_rent_eagerly (#25707)

* Bank: Batch account stores in collect_rent_eagerly

Previously store() calls were done one-by-one, which leads to suboptimal
performance.

* Accounts: Remove store_slow_cached()

* clippy

Co-authored-by: Jeff Washington (jwash) <wash678@gmail.com>
This commit is contained in:
Christian Kamm 2022-06-03 22:00:39 +02:00 committed by GitHub
parent 646bd2e488
commit 0da0e0da63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 21 deletions

View File

@ -1040,10 +1040,6 @@ impl Accounts {
self.accounts_db.store_uncached(slot, &[(pubkey, account)]); self.accounts_db.store_uncached(slot, &[(pubkey, account)]);
} }
pub fn store_slow_cached(&self, slot: Slot, pubkey: &Pubkey, account: &AccountSharedData) {
self.accounts_db.store_cached(slot, &[(pubkey, account)]);
}
fn lock_account( fn lock_account(
&self, &self,
account_locks: &mut AccountLocks, account_locks: &mut AccountLocks,
@ -1213,6 +1209,10 @@ impl Accounts {
self.accounts_db.store_cached(slot, &accounts_to_store); self.accounts_db.store_cached(slot, &accounts_to_store);
} }
pub fn store_accounts_cached(&self, slot: Slot, accounts: &[(&Pubkey, &AccountSharedData)]) {
self.accounts_db.store_cached(slot, accounts)
}
/// Add a slot to root. Root slots cannot be purged /// Add a slot to root. Root slots cannot be purged
pub fn add_root(&self, slot: Slot) -> AccountsAddRootTiming { pub fn add_root(&self, slot: Slot) -> AccountsAddRootTiming {
self.accounts_db.add_root(slot) self.accounts_db.add_root(slot)

View File

@ -5255,7 +5255,7 @@ impl Bank {
hold_range.stop(); hold_range.stop();
let mut load = Measure::start("load"); let mut load = Measure::start("load");
let accounts = self let mut accounts = self
.rc .rc
.accounts .accounts
.load_to_collect_rent_eagerly(&self.ancestors, subrange.clone()); .load_to_collect_rent_eagerly(&self.ancestors, subrange.clone());
@ -5268,16 +5268,17 @@ impl Bank {
let mut total_collected = CollectedInfo::default(); let mut total_collected = CollectedInfo::default();
let bank_slot = self.slot(); let bank_slot = self.slot();
let mut rewrites_skipped = Vec::with_capacity(accounts.len()); let mut rewrites_skipped = Vec::with_capacity(accounts.len());
let mut accounts_to_store =
Vec::<(&Pubkey, &AccountSharedData)>::with_capacity(accounts.len());
let mut collect_us = 0; let mut collect_us = 0;
let mut hash_skipped_rewrites_us = 0; let mut hash_skipped_rewrites_us = 0;
let mut store_us = 0;
let can_skip_rewrites = self.rc.accounts.accounts_db.skip_rewrites || just_rewrites; let can_skip_rewrites = self.rc.accounts.accounts_db.skip_rewrites || just_rewrites;
for (pubkey, mut account, loaded_slot) in accounts { for (pubkey, account, loaded_slot) in accounts.iter_mut() {
let old_rent_epoch = account.rent_epoch(); let old_rent_epoch = account.rent_epoch();
let mut time = Measure::start("collect"); let mut time = Measure::start("collect");
let collected = self.rent_collector.collect_from_existing_account( let collected = self.rent_collector.collect_from_existing_account(
&pubkey, pubkey,
&mut account, account,
self.rc.accounts.accounts_db.filler_account_suffix.as_ref(), self.rc.accounts.accounts_db.filler_account_suffix.as_ref(),
); );
time.stop(); time.stop();
@ -5291,9 +5292,9 @@ impl Bank {
&& Self::skip_rewrite( && Self::skip_rewrite(
bank_slot, bank_slot,
collected.rent_amount, collected.rent_amount,
loaded_slot, *loaded_slot,
old_rent_epoch, old_rent_epoch,
&account, account,
) )
{ {
// this would have been rewritten previously. Now we skip it. // this would have been rewritten previously. Now we skip it.
@ -5301,24 +5302,27 @@ impl Bank {
// This will be needed to calculate the bank's hash. // This will be needed to calculate the bank's hash.
let mut time = Measure::start("hash_account"); let mut time = Measure::start("hash_account");
let hash = let hash =
crate::accounts_db::AccountsDb::hash_account(self.slot(), &account, &pubkey); crate::accounts_db::AccountsDb::hash_account(self.slot(), account, pubkey);
time.stop(); time.stop();
hash_skipped_rewrites_us += time.as_us(); hash_skipped_rewrites_us += time.as_us();
rewrites_skipped.push((pubkey, hash)); rewrites_skipped.push((*pubkey, hash));
assert_eq!(collected, CollectedInfo::default()); assert_eq!(collected, CollectedInfo::default());
} else if !just_rewrites { } else if !just_rewrites {
let mut time = Measure::start("store_account");
total_collected += collected; total_collected += collected;
self.store_account(&pubkey, &account); accounts_to_store.push((pubkey, account));
time.stop();
store_us += time.as_us();
} }
rent_debits.insert(&pubkey, collected.rent_amount, account.lamports()); rent_debits.insert(pubkey, collected.rent_amount, account.lamports());
} }
metrics.hold_range_us.fetch_add(hold_range.as_us(), Relaxed); metrics.hold_range_us.fetch_add(hold_range.as_us(), Relaxed);
metrics.collect_us.fetch_add(collect_us, Relaxed); metrics.collect_us.fetch_add(collect_us, Relaxed);
metrics.hash_us.fetch_add(hash_skipped_rewrites_us, Relaxed); metrics.hash_us.fetch_add(hash_skipped_rewrites_us, Relaxed);
metrics.store_us.fetch_add(store_us, Relaxed);
if !accounts_to_store.is_empty() {
let mut time = Measure::start("store_account");
self.store_accounts(&accounts_to_store);
time.stop();
metrics.store_us.fetch_add(time.as_us(), Relaxed);
}
self.remember_skipped_rewrites(rewrites_skipped); self.remember_skipped_rewrites(rewrites_skipped);
self.collected_rent self.collected_rent
@ -6062,12 +6066,18 @@ impl Bank {
} }
pub fn store_account(&self, pubkey: &Pubkey, account: &AccountSharedData) { pub fn store_account(&self, pubkey: &Pubkey, account: &AccountSharedData) {
self.store_accounts(&[(pubkey, account)])
}
pub fn store_accounts(&self, accounts: &[(&Pubkey, &AccountSharedData)]) {
assert!(!self.freeze_started()); assert!(!self.freeze_started());
self.rc self.rc
.accounts .accounts
.store_slow_cached(self.slot(), pubkey, account); .store_accounts_cached(self.slot(), accounts);
let mut m = Measure::start("stakes_cache.check_and_store"); let mut m = Measure::start("stakes_cache.check_and_store");
self.stakes_cache.check_and_store(pubkey, account); for (pubkey, account) in accounts {
self.stakes_cache.check_and_store(pubkey, account);
}
m.stop(); m.stop();
self.rc self.rc
.accounts .accounts