Skip to content

Commit

Permalink
store only removes from read cache if slot is possibly present (#452)
Browse files Browse the repository at this point in the history
* store only removes from read cache if slot is possibly present

* remove_assume_not_present
  • Loading branch information
jeffwashington committed Mar 28, 2024
1 parent d5c0c0b commit e261e27
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 4 deletions.
16 changes: 12 additions & 4 deletions accounts-db/src/accounts_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6427,10 +6427,18 @@ impl AccountsDb {
) -> Vec<AccountInfo> {
let mut calc_stored_meta_time = Measure::start("calc_stored_meta");
let slot = accounts.target_slot();
(0..accounts.len()).for_each(|index| {
let pubkey = accounts.pubkey(index);
self.read_only_accounts_cache.remove(*pubkey, slot);
});
if self
.read_only_accounts_cache
.can_slot_be_in_cache(accounts.target_slot())
{
(0..accounts.len()).for_each(|index| {
let pubkey = accounts.pubkey(index);
// based on the patterns of how a validator writes accounts, it is almost always the case that there is no read only cache entry
// for this pubkey and slot. So, we can give that hint to the `remove` for performance.
self.read_only_accounts_cache
.remove_assume_not_present(*pubkey, slot);
});
}
calc_stored_meta_time.stop();
self.stats
.calc_stored_meta
Expand Down
20 changes: 20 additions & 0 deletions accounts-db/src/read_only_accounts_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,13 @@ pub(crate) struct ReadOnlyAccountsCache {

// Performance statistics
stats: ReadOnlyCacheStats,
highest_slot_stored: AtomicU64,
}

impl ReadOnlyAccountsCache {
pub(crate) fn new(max_data_size: usize, ms_to_skip_lru_update: u32) -> Self {
Self {
highest_slot_stored: AtomicU64::default(),
max_data_size,
cache: DashMap::default(),
queue: Mutex::<IndexList<ReadOnlyCacheKey>>::default(),
Expand Down Expand Up @@ -134,6 +136,7 @@ impl ReadOnlyAccountsCache {
}

pub(crate) fn store(&self, pubkey: Pubkey, slot: Slot, account: AccountSharedData) {
self.highest_slot_stored.fetch_max(slot, Ordering::Release);
let key = (pubkey, slot);
let account_size = self.account_size(&account);
self.data_size.fetch_add(account_size, Ordering::Relaxed);
Expand Down Expand Up @@ -169,6 +172,23 @@ impl ReadOnlyAccountsCache {
self.stats.evicts.fetch_add(num_evicts, Ordering::Relaxed);
}

/// true if any pubkeys could have ever been stored into the cache at `slot`
pub(crate) fn can_slot_be_in_cache(&self, slot: Slot) -> bool {
self.highest_slot_stored.load(Ordering::Acquire) >= slot
}

/// remove entry if it exists.
/// Assume the entry does not exist for performance.
pub(crate) fn remove_assume_not_present(
&self,
pubkey: Pubkey,
slot: Slot,
) -> Option<AccountSharedData> {
// get read lock first to see if the entry exists
_ = self.cache.get(&(pubkey, slot))?;
self.remove(pubkey, slot)
}

pub(crate) fn remove(&self, pubkey: Pubkey, slot: Slot) -> Option<AccountSharedData> {
let (_, entry) = self.cache.remove(&(pubkey, slot))?;
// self.queue should be modified only after removing the entry from the
Expand Down

0 comments on commit e261e27

Please sign in to comment.