Skip to content

Commit 122ab1f

Browse files
authored
perf: avoid duplicate storage get call (#20180)
1 parent bea765b commit 122ab1f

File tree

1 file changed

+43
-15
lines changed

1 file changed

+43
-15
lines changed

crates/engine/tree/src/tree/cached_state.rs

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -146,17 +146,26 @@ impl<S: StateProvider> StateProvider for CachedStateProvider<S> {
146146
storage_key: StorageKey,
147147
) -> ProviderResult<Option<StorageValue>> {
148148
match self.caches.get_storage(&account, &storage_key) {
149-
SlotStatus::NotCached => {
150-
self.metrics.storage_cache_misses.increment(1);
149+
(SlotStatus::NotCached, maybe_cache) => {
151150
let final_res = self.state_provider.storage(account, storage_key)?;
152-
self.caches.insert_storage(account, storage_key, final_res);
151+
let account_cache = maybe_cache.unwrap_or_default();
152+
account_cache.insert_storage(storage_key, final_res);
153+
// we always need to insert the value to update the weights.
154+
// Note: there exists a race when the storage cache did not exist yet and two
155+
// consumers looking up the a storage value for this account for the first time,
156+
// however we can assume that this will only happen for the very first (mostlikely
157+
// the same) value, and don't expect that this will accidentally
158+
// replace an account storage cache with additional values.
159+
self.caches.insert_storage_cache(account, account_cache);
160+
161+
self.metrics.storage_cache_misses.increment(1);
153162
Ok(final_res)
154163
}
155-
SlotStatus::Empty => {
164+
(SlotStatus::Empty, _) => {
156165
self.metrics.storage_cache_hits.increment(1);
157166
Ok(None)
158167
}
159-
SlotStatus::Value(value) => {
168+
(SlotStatus::Value(value), _) => {
160169
self.metrics.storage_cache_hits.increment(1);
161170
Ok(Some(value))
162171
}
@@ -311,18 +320,28 @@ pub(crate) struct ExecutionCache {
311320
impl ExecutionCache {
312321
/// Get storage value from hierarchical cache.
313322
///
314-
/// Returns a `SlotStatus` indicating whether:
315-
/// - `NotCached`: The account's storage cache doesn't exist
316-
/// - `Empty`: The slot exists in the account's cache but is empty
317-
/// - `Value`: The slot exists and has a specific value
318-
pub(crate) fn get_storage(&self, address: &Address, key: &StorageKey) -> SlotStatus {
323+
/// Returns a tuple of:
324+
/// - `SlotStatus` indicating whether:
325+
/// - `NotCached`: The account's storage cache doesn't exist
326+
/// - `Empty`: The slot exists in the account's cache but is empty
327+
/// - `Value`: The slot exists and has a specific value
328+
/// - `Option<Arc<AccountStorageCache>>`: The account's storage cache if it exists
329+
pub(crate) fn get_storage(
330+
&self,
331+
address: &Address,
332+
key: &StorageKey,
333+
) -> (SlotStatus, Option<Arc<AccountStorageCache>>) {
319334
match self.storage_cache.get(address) {
320-
None => SlotStatus::NotCached,
321-
Some(account_cache) => account_cache.get_storage(key),
335+
None => (SlotStatus::NotCached, None),
336+
Some(account_cache) => {
337+
let status = account_cache.get_storage(key);
338+
(status, Some(account_cache))
339+
}
322340
}
323341
}
324342

325343
/// Insert storage value into hierarchical cache
344+
#[cfg(test)]
326345
pub(crate) fn insert_storage(
327346
&self,
328347
address: Address,
@@ -351,6 +370,15 @@ impl ExecutionCache {
351370
self.storage_cache.insert(address, account_cache);
352371
}
353372

373+
/// Inserts the [`AccountStorageCache`].
374+
pub(crate) fn insert_storage_cache(
375+
&self,
376+
address: Address,
377+
storage_cache: Arc<AccountStorageCache>,
378+
) {
379+
self.storage_cache.insert(address, storage_cache);
380+
}
381+
354382
/// Invalidate storage for specific account
355383
pub(crate) fn invalidate_account_storage(&self, address: &Address) {
356384
self.storage_cache.invalidate(address);
@@ -800,7 +828,7 @@ mod tests {
800828
caches.insert_storage(address, storage_key, Some(storage_value));
801829

802830
// check that the storage returns the cached value
803-
let slot_status = caches.get_storage(&address, &storage_key);
831+
let (slot_status, _) = caches.get_storage(&address, &storage_key);
804832
assert_eq!(slot_status, SlotStatus::Value(storage_value));
805833
}
806834

@@ -814,7 +842,7 @@ mod tests {
814842
let caches = ExecutionCacheBuilder::default().build_caches(1000);
815843

816844
// check that the storage is not cached
817-
let slot_status = caches.get_storage(&address, &storage_key);
845+
let (slot_status, _) = caches.get_storage(&address, &storage_key);
818846
assert_eq!(slot_status, SlotStatus::NotCached);
819847
}
820848

@@ -830,7 +858,7 @@ mod tests {
830858
caches.insert_storage(address, storage_key, None);
831859

832860
// check that the storage is empty
833-
let slot_status = caches.get_storage(&address, &storage_key);
861+
let (slot_status, _) = caches.get_storage(&address, &storage_key);
834862
assert_eq!(slot_status, SlotStatus::Empty);
835863
}
836864

0 commit comments

Comments
 (0)