-
Notifications
You must be signed in to change notification settings - Fork 624
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: stabilize chunk nodes cache #6628
Conversation
let's also update the CHANGELOG file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code changes look great; can’t really comment on the decision of whether to stabilize or wait, since I haven't been participating in the development of this feature all that much.
Ok, this looks good to me I think! There are couple of iffy semantic moments here I want to surface, to make sure we are ok with them:
My understanding is that the The So, this gets a 👍 from me, though I'd love if someone from core/runtime took a final look here to confirm that the big picture here is exactly what we want. |
Discussed with bowenwang1996: the above should be fine, so let's merge it, but, indeed, let's not forget to update the changelog |
Stabilize feature introduced in #6450.
Motivation
For each node, for which we charge touching trie node cost (TTN), we want to do it only once per chunk - on the first access. Based on our estimation, reading node from cache requires cost ~7x lower than TTN, and it helps to reduce Aurora costs by ~27% on a sample of receipts with average 60 Tgas cost.
This is achieved by inserting these nodes into
chunk_cache
insideTrieCachingStorage
, which is automatically dropped during finishing chunk processing. We enable such caching by switching toTrieCacheMode::CachingChunk
mode, and disable it by switching back toTrieCacheMode::CachingShard
. This is currently done only during funcalls, because we don't actually charge for nodes accessed in other places.We don't set neither size limit nor maximal value limit for chunk cache items. Instead, we show that its size can't exceed 153 MB due to other runtime costs. Note for reviewers: the analysis below was updated after merging #6450.
Size limit
We store two different types of items:
RawTrieNodeWithSize
s and values, DB key for each of them is the value hash.RawTrieNodeWithSize
contains some data of limited size and sometimes a storage key part -Vec<u8>
. For limited size data,Branch
node is the worst case - here we storememory_usage
, 16Option<CryptoHash>
and 1Option<(u32, CryptoHash)>
. The total size is 8 + 16 * 33 + 40 = 576 < 600 B. Also node can contain a 2 KB key part for which we may not charge fullbyte
cost, e.g. duringstorage_has_key
query. So the overall worst case is ~2 KB, and the limit is 500 Tgas /touching_trie_node
* 2KB = 62 MB.Total size of values is limited by 500 Tgas /
storage_read_value_byte
= 500 Tgas / 5.5 Mgas ~= 91 MB. So it gives 153 MB per chunk and 612 MB for all chunks. Experiments show that on real data chunk cache size doesn't exceed 1 MB.Testing
process_blocks::chunk_nodes_cache_test
- send transaction modifying contract storage before / after protocol upgrade, check the correctness of costs.test_chunk_nodes_cache_same_common_parent_runtime
- apply 3 receipts for keys with common parent and check that cost of last 2 receipts is lower.test_chunk_nodes_cache_branch_value_runtime
- apply 2 receipts for keys where one is a prefix of another and check that cost of last receipt is lower.test_chunk_nodes_cache_mode_runtime
- check that we don't enable chunk cache for all receipts. Manual removal of disabling chunk cache mode leads to test failure.