perf(levm): add block hash caching to improve retrieval performance#6180
perf(levm): add block hash caching to improve retrieval performance#6180akshay-ap wants to merge 14 commits into
Conversation
Additional Comments (1)
Prompt To Fix With AIThis is a comment left during a code review.
Path: crates/storage/store.rs
Line: 1007:1009
Comment:
**Stale canonical cache**
`forkchoice_update_inner` deletes canonical hashes for `(head_number + 1)..=latest` in the DB, but `block_hash_cache` is never purged for those block numbers. Because `get_canonical_block_hash_sync` checks the LRU before hitting the DB, a reorg that truncates the chain can cause this method to return a hash for a block number that is no longer canonical (or no longer present in `CANONICAL_BLOCK_HASHES`). You likely need to invalidate cache entries for the deleted range when applying the reorg.
How can I resolve this? If you propose a fix, please make it concise. |
There was a problem hiding this comment.
Pull request overview
This pull request adds an LRU cache for block hash lookups to improve retrieval performance in the storage layer. The cache stores mappings from block numbers to block hashes, reducing the need to query the database for frequently accessed canonical block hashes.
Changes:
- Added a 256-entry LRU cache for block number to block hash mappings
- Integrated cache lookups in
get_canonical_block_hash_syncmethod with fallback to database - Updated
forkchoice_update_innerto populate cache when canonical blocks are written to the database
Comments suppressed due to low confidence (1)
crates/storage/store.rs:1165
- The cache is not populated when reading from the database (read-through caching is missing). Following the pattern established by account_code_cache (lines 678-712), when there's a cache miss, the value should be inserted into the cache after being read from the database. Add cache population logic after the database read at lines 1157-1164 to improve cache effectiveness and future read performance.
// Cache miss: read from database
let txn = self.backend.begin_read()?;
txn.get(
CANONICAL_BLOCK_HASHES,
block_number.to_le_bytes().as_slice(),
)?
.map(|bytes| H256::decode(bytes.as_slice()))
.transpose()
.map_err(StoreError::from)
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
d24cac0 to
5c8cdfc
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
crates/storage/store.rs:1415
- On a cache miss, the block hash is read from the DB but never inserted into
block_hash_cache. This means repeated lookups for the same block number (e.g., after restart before the cache is warmed, or for frequently queried older blocks) will keep hitting the backend.
After decoding a non-None hash from CANONICAL_BLOCK_HASHES, insert it into the LRU cache (best-effort) before returning.
// Cache miss: read from database
let txn = self.backend.begin_read()?;
txn.get(
CANONICAL_BLOCK_HASHES,
block_number.to_le_bytes().as_slice(),
Fixes #5689