chore(trie): Spans and traces for sparse trie (#21973)

This commit is contained in:
Brian Picciano
2026-02-09 12:53:40 +01:00
committed by GitHub
parent 655a463c18
commit 6aebf8c064
3 changed files with 49 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
---
reth-engine-tree: patch
reth-trie-sparse-parallel: patch
---
Added tracing spans and debug logs to sparse trie operations for better observability during parallel state root computation.

View File

@@ -623,6 +623,7 @@ where
if new { &mut self.new_storage_updates } else { &mut self.storage_updates };
// Process all storage updates in parallel, skipping tries with no pending updates.
let span = tracing::Span::current();
let storage_results = storage_updates
.iter_mut()
.filter(|(_, updates)| !updates.is_empty())
@@ -634,6 +635,7 @@ where
})
.par_bridge_buffered()
.map(|(address, updates, mut fetched, mut trie)| {
let _enter = debug_span!(target: "engine::tree::payload_processor::sparse_trie", parent: &span, "storage trie leaf updates", ?address).entered();
let mut targets = Vec::new();
trie.update_leaves(updates, |path, min_len| match fetched.entry(path) {
@@ -653,6 +655,8 @@ where
})
.collect::<Result<Vec<_>, _>>()?;
drop(span);
for (address, targets, fetched, trie) in storage_results {
self.fetched_storage_targets.insert(*address, fetched);
self.trie.insert_storage_trie(*address, trie);
@@ -714,6 +718,7 @@ where
return Ok(());
}
let span = tracing::Span::current();
let roots = self
.trie
.storage_tries_mut()
@@ -722,6 +727,7 @@ where
self.storage_updates.get(*address).is_some_and(|updates| updates.is_empty())
})
.map(|(address, trie)| {
let _enter = debug_span!(target: "engine::tree::payload_processor::sparse_trie", parent: &span, "storage root", ?address).entered();
let root =
trie.root().expect("updates are drained, trie should be revealed by now");

View File

@@ -259,6 +259,10 @@ impl SparseTrie for ParallelSparseTrie {
// Reveal lower subtrie nodes in parallel
{
use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
use tracing::Span;
// Capture the current span so it can be propagated to rayon worker threads
let parent_span = Span::current();
// Capture reference to upper subtrie nodes for boundary leaf reachability checks
let upper_nodes = &self.upper_subtrie.nodes;
@@ -309,6 +313,10 @@ impl SparseTrie for ParallelSparseTrie {
.into_par_iter()
.zip(node_groups.into_par_iter())
.map(|((subtrie_idx, mut subtrie), nodes)| {
// Enter the parent span to propagate context (e.g., hashed_address for storage
// tries) to the worker thread
let _guard = parent_span.enter();
// reserve space in the HashMap ahead of time; doing it on a node-by-node basis
// can cause multiple re-allocations as the hashmap grows.
subtrie.nodes.reserve(nodes.len());
@@ -360,6 +368,13 @@ impl SparseTrie for ParallelSparseTrie {
value: Vec<u8>,
provider: P,
) -> SparseTrieResult<()> {
trace!(
target: "trie::parallel_sparse",
?full_path,
value_len = value.len(),
"Updating leaf",
);
// Check if the value already exists - if so, just update it (no structural changes needed)
if self.upper_subtrie.inner.values.contains_key(&full_path) {
self.prefix_set.insert(full_path);
@@ -611,6 +626,12 @@ impl SparseTrie for ParallelSparseTrie {
full_path: &Nibbles,
provider: P,
) -> SparseTrieResult<()> {
trace!(
target: "trie::parallel_sparse",
?full_path,
"Removing leaf",
);
// When removing a leaf node it's possibly necessary to modify its parent node, and possibly
// the parent's parent node. It is not ever necessary to descend further than that; once an
// extension node is hit it must terminate in a branch or the root, which won't need further
@@ -2787,6 +2808,14 @@ impl SparseSubtrie {
return Ok(false)
}
trace!(
target: "trie::parallel_sparse",
?path,
?node,
?masks,
"Revealing node",
);
match node {
TrieNode::EmptyRoot => {
// For an empty root, ensure that we are at the root path, and at the upper subtrie.
@@ -3147,6 +3176,14 @@ impl SparseSubtrieInner {
self.buffers.rlp_buf.clear();
let rlp_node = LeafNodeRef { key, value }.rlp(&mut self.buffers.rlp_buf);
*hash = rlp_node.as_hash();
trace!(
target: "trie::parallel_sparse",
?path,
?key,
value = %alloy_primitives::hex::encode(value),
?hash,
"Calculated leaf hash",
);
(rlp_node, SparseNodeType::Leaf)
}
}