revert: perf(trie): parallelize merge_ancestors_into_overlay (#21202) (#21370)

This commit is contained in:
Georgios Konstantopoulos
2026-01-23 10:09:19 -08:00
committed by GitHub
parent c137ed836f
commit dd0c6d279f
3 changed files with 3 additions and 109 deletions

View File

@@ -243,53 +243,8 @@ impl DeferredTrieData {
/// In normal operation, the parent always has a cached overlay and this
/// function is never called.
///
/// When the `rayon` feature is enabled, uses parallel collection and merge:
/// 1. Collects ancestor data in parallel (each `wait_cloned()` may compute)
/// 2. Merges hashed state and trie updates in parallel with each other
/// 3. Uses tree reduction within each merge for O(log n) depth
#[cfg(feature = "rayon")]
fn merge_ancestors_into_overlay(
ancestors: &[Self],
sorted_hashed_state: &HashedPostStateSorted,
sorted_trie_updates: &TrieUpdatesSorted,
) -> TrieInputSorted {
// Early exit: no ancestors means just wrap current block's data
if ancestors.is_empty() {
return TrieInputSorted::new(
Arc::new(sorted_trie_updates.clone()),
Arc::new(sorted_hashed_state.clone()),
Default::default(),
);
}
// Collect ancestor data, unzipping states and updates into Arc slices
let (states, updates): (Vec<_>, Vec<_>) = ancestors
.iter()
.map(|a| {
let data = a.wait_cloned();
(data.hashed_state, data.trie_updates)
})
.unzip();
// Merge state and nodes in parallel with each other using tree reduction
let (state, nodes) = rayon::join(
|| {
let mut merged = HashedPostStateSorted::merge_parallel(&states);
merged.extend_ref_and_sort(sorted_hashed_state);
merged
},
|| {
let mut merged = TrieUpdatesSorted::merge_parallel(&updates);
merged.extend_ref_and_sort(sorted_trie_updates);
merged
},
);
TrieInputSorted::new(Arc::new(nodes), Arc::new(state), Default::default())
}
/// Merge all ancestors and current block's data into a single overlay (sequential fallback).
#[cfg(not(feature = "rayon"))]
/// Iterates ancestors oldest -> newest, then extends with current block's data,
/// so later state takes precedence.
fn merge_ancestors_into_overlay(
ancestors: &[Self],
sorted_hashed_state: &HashedPostStateSorted,

View File

@@ -6,7 +6,7 @@ use crate::{
utils::{extend_sorted_vec, kway_merge_sorted},
KeyHasher, MultiProofTargets, Nibbles,
};
use alloc::{borrow::Cow, sync::Arc, vec::Vec};
use alloc::{borrow::Cow, vec::Vec};
use alloy_primitives::{
keccak256,
map::{hash_map, B256Map, HashMap, HashSet},
@@ -710,36 +710,6 @@ impl HashedPostStateSorted {
self.accounts.clear();
self.storages.clear();
}
/// Parallel batch-merge sorted hashed post states. Slice is **oldest to newest**.
///
/// This is more efficient than sequential `extend_ref` calls when merging many states,
/// as it processes all states in parallel with tree reduction using divide-and-conquer.
#[cfg(feature = "rayon")]
pub fn merge_parallel(states: &[Arc<Self>]) -> Self {
fn parallel_merge_tree(states: &[Arc<HashedPostStateSorted>]) -> HashedPostStateSorted {
match states.len() {
0 => HashedPostStateSorted::default(),
1 => states[0].as_ref().clone(),
2 => {
let mut acc = states[0].as_ref().clone();
acc.extend_ref_and_sort(&states[1]);
acc
}
n => {
let mid = n / 2;
let (mut left, right) = rayon::join(
|| parallel_merge_tree(&states[..mid]),
|| parallel_merge_tree(&states[mid..]),
);
left.extend_ref_and_sort(&right);
left
}
}
}
parallel_merge_tree(states)
}
}
impl AsRef<Self> for HashedPostStateSorted {

View File

@@ -4,7 +4,6 @@ use crate::{
};
use alloc::{
collections::{btree_map::BTreeMap, btree_set::BTreeSet},
sync::Arc,
vec::Vec,
};
use alloy_primitives::{
@@ -698,36 +697,6 @@ impl TrieUpdatesSorted {
Self { account_nodes, storage_tries }.into()
}
/// Parallel batch-merge sorted trie updates. Slice is **oldest to newest**.
///
/// This is more efficient than sequential `extend_ref` calls when merging many updates,
/// as it processes all updates in parallel with tree reduction using divide-and-conquer.
#[cfg(feature = "rayon")]
pub fn merge_parallel(updates: &[Arc<Self>]) -> Self {
fn parallel_merge_tree(updates: &[Arc<TrieUpdatesSorted>]) -> TrieUpdatesSorted {
match updates.len() {
0 => TrieUpdatesSorted::default(),
1 => updates[0].as_ref().clone(),
2 => {
let mut acc = updates[0].as_ref().clone();
acc.extend_ref_and_sort(&updates[1]);
acc
}
n => {
let mid = n / 2;
let (mut left, right) = rayon::join(
|| parallel_merge_tree(&updates[..mid]),
|| parallel_merge_tree(&updates[mid..]),
);
left.extend_ref_and_sort(&right);
left
}
}
}
parallel_merge_tree(updates)
}
}
impl AsRef<Self> for TrieUpdatesSorted {