From 8cb506c4d3bf90aebfcb51221c5fbe96194e1f07 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Wed, 14 Jan 2026 19:26:23 +0000 Subject: [PATCH] perf: don't clone entire keys set (#21042) --- .../src/tree/payload_processor/multiproof.rs | 43 ++++++++++++++++++- crates/trie/common/src/added_removed_keys.rs | 6 ++- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/crates/engine/tree/src/tree/payload_processor/multiproof.rs b/crates/engine/tree/src/tree/payload_processor/multiproof.rs index b502e4decf..db44b1f98d 100644 --- a/crates/engine/tree/src/tree/payload_processor/multiproof.rs +++ b/crates/engine/tree/src/tree/payload_processor/multiproof.rs @@ -20,6 +20,7 @@ use reth_trie_parallel::{ AccountMultiproofInput, ProofResultContext, ProofResultMessage, ProofWorkerHandle, }, }; +use revm_primitives::map::{hash_map, B256Map}; use std::{collections::BTreeMap, sync::Arc, time::Instant}; use tracing::{debug, error, instrument, trace}; @@ -609,7 +610,19 @@ impl MultiProofTask { self.multi_added_removed_keys.touch_accounts(targets.keys().copied()); // Clone+Arc MultiAddedRemovedKeys for sharing with the dispatched multiproof tasks - let multi_added_removed_keys = Arc::new(self.multi_added_removed_keys.clone()); + let multi_added_removed_keys = Arc::new(MultiAddedRemovedKeys { + account: self.multi_added_removed_keys.account.clone(), + storages: targets + .keys() + .filter_map(|account| { + self.multi_added_removed_keys + .storages + .get(account) + .cloned() + .map(|keys| (*account, keys)) + }) + .collect(), + }); self.metrics.prefetch_proof_targets_accounts_histogram.record(targets.len() as f64); self.metrics @@ -705,7 +718,33 @@ impl MultiProofTask { } // Clone+Arc MultiAddedRemovedKeys for sharing with the dispatched multiproof tasks - let multi_added_removed_keys = Arc::new(self.multi_added_removed_keys.clone()); + let multi_added_removed_keys = Arc::new(MultiAddedRemovedKeys { + account: self.multi_added_removed_keys.account.clone(), + storages: { + let mut storages = B256Map::with_capacity_and_hasher( + not_fetched_state_update.storages.len(), + Default::default(), + ); + + for account in not_fetched_state_update + .storages + .keys() + .chain(not_fetched_state_update.accounts.keys()) + { + if let hash_map::Entry::Vacant(entry) = storages.entry(*account) { + entry.insert( + self.multi_added_removed_keys + .storages + .get(account) + .cloned() + .unwrap_or_default(), + ); + } + } + + storages + }, + }); let chunking_len = not_fetched_state_update.chunking_length(); let mut spawned_proof_targets = MultiProofTargets::default(); diff --git a/crates/trie/common/src/added_removed_keys.rs b/crates/trie/common/src/added_removed_keys.rs index 8e61423718..34a4561dad 100644 --- a/crates/trie/common/src/added_removed_keys.rs +++ b/crates/trie/common/src/added_removed_keys.rs @@ -7,8 +7,10 @@ use alloy_trie::proof::AddedRemovedKeys; /// Tracks added and removed keys across account and storage tries. #[derive(Debug, Clone)] pub struct MultiAddedRemovedKeys { - account: AddedRemovedKeys, - storages: B256Map, + /// Added and removed accounts. + pub account: AddedRemovedKeys, + /// Added and removed storage keys for each account. + pub storages: B256Map, } /// Returns [`AddedRemovedKeys`] with default parameters. This is necessary while we are not yet