From 5b481a34a2d364dc85aa128355959c04574508e6 Mon Sep 17 00:00:00 2001 From: jeff washington Date: Thu, 20 Jul 2023 13:36:19 -0500 Subject: [PATCH] update lru for read only cache if it has been long enough since last access --- runtime/src/read_only_accounts_cache.rs | 37 +++++++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/runtime/src/read_only_accounts_cache.rs b/runtime/src/read_only_accounts_cache.rs index eaa1cd263ace67..e9a8c9a119fb4d 100644 --- a/runtime/src/read_only_accounts_cache.rs +++ b/runtime/src/read_only_accounts_cache.rs @@ -8,6 +8,7 @@ use { account::{AccountSharedData, ReadableAccount}, clock::Slot, pubkey::Pubkey, + timing::timestamp, }, std::sync::{ atomic::{AtomicU64, AtomicUsize, Ordering}, @@ -23,7 +24,28 @@ type ReadOnlyCacheKey = (Pubkey, Slot); #[derive(Debug)] struct ReadOnlyAccountCacheEntry { account: AccountSharedData, - index: Index, // Index of the entry in the eviction queue. + /// Index of the entry in the eviction queue. + index: Index, + /// lower bits of last timestamp when eviction queue was updated + last_time: u32, +} + +impl ReadOnlyAccountCacheEntry { + fn new(account: AccountSharedData, index: Index) -> Self { + Self { + account, + index, + last_time: Self::timestamp(), + } + } + /// lower bits of current timestamp. We don't need higher bits and u32 fits with Index u32 + fn timestamp() -> u32 { + (timestamp() % (u32::MAX as u64 + 1)) as u32 + } + /// ms since `last_time` timestamp + fn ms_since_last_time(&self) -> u32 { + Self::timestamp().wrapping_sub(self.last_time) + } } #[derive(Debug)] @@ -78,16 +100,19 @@ impl ReadOnlyAccountsCache { let (account, load_us) = measure_us!({ let key = (pubkey, slot); let Some(mut entry) = self.cache.get_mut(&key) else { - self.misses.fetch_add(1, Ordering::Relaxed); - return None; - }; + self.misses.fetch_add(1, Ordering::Relaxed); + return None; + }; // Move the entry to the end of the queue. // self.queue is modified while holding a reference to the cache entry; // so that another thread cannot write to the same key. - { + // If we updated the eviction queue within this much time, then leave it where it is. We're likely to hit it again. + let update_lru = entry.ms_since_last_time() > 500; + if update_lru { let mut queue = self.queue.lock().unwrap(); queue.remove(entry.index); entry.index = queue.insert_last(key); + entry.last_time = ReadOnlyAccountCacheEntry::timestamp(); } let account = entry.account.clone(); drop(entry); @@ -113,7 +138,7 @@ impl ReadOnlyAccountsCache { // Insert the entry at the end of the queue. let mut queue = self.queue.lock().unwrap(); let index = queue.insert_last(key); - entry.insert(ReadOnlyAccountCacheEntry { account, index }); + entry.insert(ReadOnlyAccountCacheEntry::new(account, index)); } Entry::Occupied(mut entry) => { let entry = entry.get_mut();