feat(btreemap): add direct-mapped node cache for read operations#416
feat(btreemap): add direct-mapped node cache for read operations#416sasa-tomic merged 55 commits intomainfrom
Conversation
Add a 32-slot direct-mapped node cache to BTreeMap that avoids re-loading hot nodes from stable memory. Modeled after CPU caches: O(1) lookup via (address / page_size) % 32, collision = eviction. Read paths (get, contains_key, first/last_key_value) use a take+return pattern to borrow nodes from the cache without RefCell lifetime issues. Write paths (insert, remove, split, merge) invalidate affected cache slots. Key changes: - Switch get() from destructive extract_entry_at to node.value() - Remove unused extract_entry_at method - Change traverse() closure from Fn(&mut Node) to Fn(&Node) - Invalidate cache in save_node, deallocate_node, merge, clear_new Expected improvement: ~15-20% for random reads, ~65% for hot-key workloads, ~0% overhead for writes (cache.get_mut() bypasses RefCell).
|
|
|
|
|
|
…expose hit/miss stats
sasa-tomic
left a comment
There was a problem hiding this comment.
Addressing open review comments with code changes and replies.
…ard NULL - Change DEFAULT_NODE_CACHE_NUM_SLOTS from 0 to 16 (covers top 2 tree levels) - Remove redundant cache_num_slots field from BTreeMap; NodeCache methods now self-guard via is_enabled() and callers no longer need checks - Add NULL address guard in NodeCache::take to prevent false cache hits
maksymar
left a comment
There was a problem hiding this comment.
Great results! 🎉 Thank you!
|
[DONE] |

Motivation
Solution
with_node_cache()andnode_cache_resize().NodeCacheMetricsfor monitoring hit ratio, cold misses, and collision misses.read_value_uncached()to avoid inflating cached nodes with large values.Impact
Details
get(),contains_key(),first/last_entry()now use the cache.insert,remove,merge) invalidate affected cache slots.Related to #166