accounts hash calls maybe_rehash_skipped_rewrite (#24316)

This commit is contained in:
Jeff Washington (jwash) 2022-04-19 08:29:09 -05:00 committed by GitHub
parent 16222553b8
commit dc98510d6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 6 deletions

View File

@ -40,6 +40,7 @@ use {
append_vec::{AppendVec, StoredAccountMeta, StoredMeta, StoredMetaWriteVersion},
cache_hash_data::CacheHashData,
contains::Contains,
expected_rent_collection::ExpectedRentCollection,
pubkey_bins::PubkeyBinCalculator24,
read_only_accounts_cache::ReadOnlyAccountsCache,
rent_collector::RentCollector,
@ -5137,6 +5138,11 @@ impl AccountsDb {
);
}
/// find slot >= 'slot' which is a root or in 'ancestors'
pub fn find_unskipped_slot(&self, slot: Slot, ancestors: Option<&Ancestors>) -> Option<Slot> {
self.accounts_index.get_next_original_root(slot, ancestors)
}
pub fn checked_iterative_sum_for_capitalization(total_cap: u64, new_cap: u64) -> u64 {
let new_total = total_cap as u128 + new_cap as u128;
AccountsHash::checked_cast_for_capitalization(new_total)
@ -5171,6 +5177,8 @@ impl AccountsDb {
// We'll also accumulate the lamports within each chunk and fewer chunks results in less contention to accumulate the sum.
let chunks = crate::accounts_hash::MERKLE_FANOUT.pow(4);
let total_lamports = Mutex::<u64>::new(0);
let stats = HashStats::default();
let get_hashes = || {
keys.par_chunks(chunks)
.map(|pubkeys| {
@ -5203,7 +5211,22 @@ impl AccountsDb {
.get_loaded_account()
.and_then(
|loaded_account| {
let find_unskipped_slot = |slot: Slot| {
self.find_unskipped_slot(slot, config.ancestors)
};
let loaded_hash = loaded_account.loaded_hash();
let new_hash = ExpectedRentCollection::maybe_rehash_skipped_rewrite(
&loaded_account,
&loaded_hash,
pubkey,
*slot,
config.rent_collector,
&stats,
max_slot + 1, // this wants an 'exclusive' number
find_unskipped_slot,
self.filler_account_suffix.as_ref(),
);
let loaded_hash = new_hash.unwrap_or(loaded_hash);
let balance = loaded_account.lamports();
if config.check_hash && !self.is_filler_account(pubkey) { // this will not be supported anymore
let computed_hash =
@ -5260,6 +5283,16 @@ impl AccountsDb {
("hash", hash_time.as_us(), i64),
("hash_total", hash_total, i64),
("collect", collect.as_us(), i64),
(
"rehashed_rewrites",
stats.rehash_required.load(Ordering::Relaxed),
i64
),
(
"rehashed_rewrites_unnecessary",
stats.rehash_unnecessary.load(Ordering::Relaxed),
i64
),
);
Ok((accumulated_hash, total_lamports))
}
@ -5663,6 +5696,8 @@ impl AccountsDb {
let range = bin_range.end - bin_range.start;
let sort_time = AtomicU64::new(0);
let find_unskipped_slot = |slot: Slot| self.find_unskipped_slot(slot, config.ancestors);
let result: Vec<BinnedHashData> = self.scan_account_storage_no_bank(
cache_hash_data,
config,
@ -5685,8 +5720,21 @@ impl AccountsDb {
raw_lamports
};
let source_item =
CalculateHashIntermediate::new(loaded_account.loaded_hash(), balance, *pubkey);
let loaded_hash = loaded_account.loaded_hash();
let new_hash = ExpectedRentCollection::maybe_rehash_skipped_rewrite(
&loaded_account,
&loaded_hash,
pubkey,
slot,
config.rent_collector,
stats,
storage.range().end,
find_unskipped_slot,
filler_account_suffix,
);
let loaded_hash = new_hash.unwrap_or(loaded_hash);
let source_item = CalculateHashIntermediate::new(loaded_hash, balance, *pubkey);
if config.check_hash
&& !Self::is_filler_account_helper(pubkey, filler_account_suffix)

View File

@ -11,7 +11,7 @@ use {
borrow::Borrow,
convert::TryInto,
sync::{
atomic::{AtomicUsize, Ordering},
atomic::{AtomicU64, AtomicUsize, Ordering},
Mutex,
},
},
@ -70,6 +70,10 @@ pub struct HashStats {
pub min_bin_size: usize,
pub max_bin_size: usize,
pub storage_size_quartiles: StorageSizeQuartileStats,
/// time spent hashing during rehash calls
pub rehash_hash_us: AtomicU64,
/// time spent determining whether to rehash during rehash calls
pub rehash_calc_us: AtomicU64,
/// # rehashes that took place and were necessary
pub rehash_required: AtomicUsize,
/// # rehashes that took place and were UNnecessary
@ -173,6 +177,16 @@ impl HashStats {
self.rehash_required.load(Ordering::Relaxed) as i64,
i64
),
(
"rehash_hash_us",
self.rehash_hash_us.load(Ordering::Relaxed) as i64,
i64
),
(
"rehash_calc_us",
self.rehash_calc_us.load(Ordering::Relaxed) as i64,
i64
),
(
"rehashed_rewrites_unnecessary",
self.rehash_unnecessary.load(Ordering::Relaxed) as i64,

View File

@ -396,7 +396,9 @@ impl ExpectedRentCollection {
find_unskipped_slot: impl Fn(Slot) -> Option<Slot>,
filler_account_suffix: Option<&Pubkey>,
) -> Option<Hash> {
let expected = match ExpectedRentCollection::new(
use solana_measure::measure::Measure;
let mut m = Measure::start("rehash_calc_us");
let expected = ExpectedRentCollection::new(
pubkey,
loaded_account,
storage_slot,
@ -404,20 +406,26 @@ impl ExpectedRentCollection {
max_slot_in_storages_exclusive,
find_unskipped_slot,
filler_account_suffix,
) {
);
m.stop();
stats.rehash_calc_us.fetch_add(m.as_us(), Ordering::Relaxed);
let expected = match expected {
None => {
// use the previously calculated hash
return None;
}
Some(expected) => expected,
};
let mut m = Measure::start("rehash_hash_us");
let recalc_hash = AccountsDb::hash_account_with_rent_epoch(
expected.expected_rent_collection_slot_max_epoch,
loaded_account,
pubkey,
expected.rent_epoch,
);
m.stop();
stats.rehash_hash_us.fetch_add(m.as_us(), Ordering::Relaxed);
if &recalc_hash == loaded_hash {
// unnecessary calculation occurred
stats.rehash_unnecessary.fetch_add(1, Ordering::Relaxed);