starknet_patricia,starknet_patricia_storage: cut redundant hashmap work in per-block hot paths#14853
starknet_patricia,starknet_patricia_storage: cut redundant hashmap work in per-block hot paths#14853gkaempfer wants to merge 1 commit into
Conversation
…rk in per-block hot paths Follow-up performance review of #14850. - RocksDbStorage::mset iterated key_to_value.keys() and then re-looked-up each value via key_to_value[key], hashing and probing the map twice per key on every block's batch write. Use .iter() to get (key, value) pairs directly, as multi_set_and_delete already does. - FilledTreeImpl::initialize_filled_tree_output_map_with_placeholders builds its output map via `.filter_map(...).collect()`. filter_map's size_hint lower bound is always 0, so collect (and the Extend impl backing it) could not preallocate, reintroducing the O(log N) rehash-on-grow cost that a prior fix (#14641) had removed from this same function before it was rewritten to use OnceLock placeholders. Reserve capacity using the (exact) unfiltered node count instead. 🤖 Generated with Claude Code
PR SummaryLow Risk Overview
Reviewed by Cursor Bugbot for commit 4908dc1. Bugbot is set up for automated code reviews on this repo. Configure here. |
Summary
Follow-up performance review of #14850 (
starknet_patricia_storage: remove redundant copy in create_db_key), scoped to two more hot-path hashmap inefficiencies found while auditing the surrounding storage/commit code.1.
RocksDbStorage::mset— redundant hashmap re-lookup per keymsetiterated.keys()and then re-looked-up each value viakey_to_value[key](theIndeximpl), hashing and probing the map a second time for every one of the O(N_nodes) entries written per block..iter()yields(key, value)directly — same patternmulti_set_and_deleteright below it already uses.2.
FilledTreeImpl::initialize_filled_tree_output_map_with_placeholders— lost capacity hint after theOnceLockrefactorThis function used to build its output map with an explicit
with_capacityhint (added in #14641 to avoid O(log N) rehash-on-grow). It has since been rewritten toupdated_skeleton.get_nodes().filter_map(...).collect()as part of switching placeholders fromMutex<Option<T>>toOnceLock<T>.filter_map'ssize_hint()lower bound is always 0 (filtering may drop every element), socollect/extendcan no longer preallocate, silently reintroducing the rehashing cost the earlier fix removed.get_nodes()is backed by a plainHashMap::iter(), so itssize_hint().0is exact — reserving on the unfiltered count is a safe (tight) upper bound for the filtered map, with identical resulting contents.Test plan
cargo build -p starknet_patricia -p starknet_patricia_storageSEED=0 cargo test -p starknet_patricia— 107 passedSEED=0 cargo test -p starknet_patricia_storage— 8 passed, includingstorage_test::test_storage_concurrent_access::case_1_rocksdb_storagewhich exercises themsetpathfilter_map's size_hint semantics, confirmedget_nodes()'s size_hint is exact, confirmed no double-consume/behavior change, no blocking or suggestion findings🤖 Generated with Claude Code
Generated by Claude Code