mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-02-19 03:04:27 -05:00
perf(trie): use TrieMask iterator for efficient bit iteration (#21676)
This commit is contained in:
33
Cargo.lock
generated
33
Cargo.lock
generated
@@ -938,9 +938,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-trie"
|
||||
version = "0.9.3"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "428aa0f0e0658ff091f8f667c406e034b431cb10abd39de4f507520968acc499"
|
||||
checksum = "4d7fd448ab0a017de542de1dcca7a58e7019fe0e7a34ed3f9543ebddf6aceffa"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-rlp",
|
||||
@@ -950,9 +950,10 @@ dependencies = [
|
||||
"derive_more",
|
||||
"nybbles",
|
||||
"proptest",
|
||||
"proptest-derive 0.5.1",
|
||||
"proptest-derive 0.7.0",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"thiserror 2.0.18",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@@ -1019,7 +1020,7 @@ version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1030,7 +1031,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3111,7 +3112,7 @@ dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users 0.5.2",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3441,7 +3442,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5182,7 +5183,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6146,7 +6147,7 @@ version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7080,9 +7081,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proptest-derive"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49"
|
||||
checksum = "095a99f75c69734802359b682be8daaf8980296731f6470434ea2c652af1dd30"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -7091,9 +7092,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proptest-derive"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "095a99f75c69734802359b682be8daaf8980296731f6470434ea2c652af1dd30"
|
||||
checksum = "fb6dc647500e84a25a85b100e76c85b8ace114c209432dc174f20aac11d4ed6c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -11787,7 +11788,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -12647,7 +12648,7 @@ dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -13891,7 +13892,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -492,7 +492,7 @@ alloy-eip2124 = { version = "0.2.0", default-features = false }
|
||||
alloy-eip7928 = { version = "0.3.0", default-features = false }
|
||||
alloy-evm = { version = "0.27.2", default-features = false }
|
||||
alloy-rlp = { version = "0.3.10", default-features = false, features = ["core-net"] }
|
||||
alloy-trie = { version = "0.9.1", default-features = false }
|
||||
alloy-trie = { version = "0.9.4", default-features = false }
|
||||
|
||||
alloy-hardforks = "0.4.5"
|
||||
|
||||
|
||||
@@ -85,4 +85,6 @@ pub mod serde_bincode_compat {
|
||||
}
|
||||
|
||||
/// Re-export
|
||||
pub use alloy_trie::{nodes::*, proof, BranchNodeCompact, HashBuilder, TrieMask, EMPTY_ROOT_HASH};
|
||||
pub use alloy_trie::{
|
||||
nodes::*, proof, BranchNodeCompact, HashBuilder, TrieMask, TrieMaskIter, EMPTY_ROOT_HASH,
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ use reth_execution_errors::{SparseTrieError, SparseTrieErrorKind, SparseTrieResu
|
||||
use reth_trie_common::{
|
||||
prefix_set::{PrefixSet, PrefixSetMut},
|
||||
BranchNodeMasks, BranchNodeMasksMap, BranchNodeRef, ExtensionNodeRef, LeafNodeRef, Nibbles,
|
||||
ProofTrieNode, RlpNode, TrieNode, CHILD_INDEX_RANGE,
|
||||
ProofTrieNode, RlpNode, TrieNode,
|
||||
};
|
||||
use reth_trie_sparse::{
|
||||
provider::{RevealedNode, TrieNodeProvider},
|
||||
@@ -2087,15 +2087,13 @@ impl ParallelSparseTrie {
|
||||
// in the lower subtrie, and reveal accordingly.
|
||||
if !SparseSubtrieType::path_len_is_upper(path.len() + 1) {
|
||||
let mut stack_ptr = branch.as_ref().first_child_index();
|
||||
for idx in CHILD_INDEX_RANGE {
|
||||
if branch.state_mask.is_bit_set(idx) {
|
||||
let mut child_path = path;
|
||||
child_path.push_unchecked(idx);
|
||||
self.lower_subtrie_for_path_mut(&child_path)
|
||||
.expect("child_path must have a lower subtrie")
|
||||
.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
|
||||
stack_ptr += 1;
|
||||
}
|
||||
for idx in branch.state_mask.iter() {
|
||||
let mut child_path = path;
|
||||
child_path.push_unchecked(idx);
|
||||
self.lower_subtrie_for_path_mut(&child_path)
|
||||
.expect("child_path must have a lower subtrie")
|
||||
.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
|
||||
stack_ptr += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2629,19 +2627,17 @@ impl SparseSubtrie {
|
||||
self.nodes.insert(path, SparseNode::Empty);
|
||||
}
|
||||
TrieNode::Branch(branch) => {
|
||||
// For a branch node, iterate over all potential children
|
||||
// For a branch node, iterate over all children
|
||||
let mut stack_ptr = branch.as_ref().first_child_index();
|
||||
for idx in CHILD_INDEX_RANGE {
|
||||
if branch.state_mask.is_bit_set(idx) {
|
||||
let mut child_path = path;
|
||||
child_path.push_unchecked(idx);
|
||||
if Self::is_child_same_level(&path, &child_path) {
|
||||
// Reveal each child node or hash it has, but only if the child is on
|
||||
// the same level as the parent.
|
||||
self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
|
||||
}
|
||||
stack_ptr += 1;
|
||||
for idx in branch.state_mask.iter() {
|
||||
let mut child_path = path;
|
||||
child_path.push_unchecked(idx);
|
||||
if Self::is_child_same_level(&path, &child_path) {
|
||||
// Reveal each child node or hash it has, but only if the child is on
|
||||
// the same level as the parent.
|
||||
self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
|
||||
}
|
||||
stack_ptr += 1;
|
||||
}
|
||||
// Update the branch node entry in the nodes map, handling cases where a blinded
|
||||
// node is now replaced with a revealed node.
|
||||
@@ -3071,12 +3067,10 @@ impl SparseSubtrieInner {
|
||||
self.buffers.branch_child_buf.clear();
|
||||
// Walk children in a reverse order from `f` to `0`, so we pop the `0` first
|
||||
// from the stack and keep walking in the sorted order.
|
||||
for bit in CHILD_INDEX_RANGE.rev() {
|
||||
if state_mask.is_bit_set(bit) {
|
||||
let mut child = path;
|
||||
child.push_unchecked(bit);
|
||||
self.buffers.branch_child_buf.push(child);
|
||||
}
|
||||
for bit in state_mask.iter().rev() {
|
||||
let mut child = path;
|
||||
child.push_unchecked(bit);
|
||||
self.buffers.branch_child_buf.push(child);
|
||||
}
|
||||
|
||||
self.buffers
|
||||
|
||||
@@ -21,8 +21,7 @@ use reth_execution_errors::{SparseTrieErrorKind, SparseTrieResult};
|
||||
use reth_trie_common::{
|
||||
prefix_set::{PrefixSet, PrefixSetMut},
|
||||
BranchNodeCompact, BranchNodeMasks, BranchNodeMasksMap, BranchNodeRef, ExtensionNodeRef,
|
||||
LeafNodeRef, Nibbles, ProofTrieNode, RlpNode, TrieMask, TrieNode, CHILD_INDEX_RANGE,
|
||||
EMPTY_ROOT_HASH,
|
||||
LeafNodeRef, Nibbles, ProofTrieNode, RlpNode, TrieMask, TrieNode, EMPTY_ROOT_HASH,
|
||||
};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
@@ -422,13 +421,11 @@ impl fmt::Display for SerialSparseTrie {
|
||||
SparseNode::Branch { state_mask, .. } => {
|
||||
writeln!(f, "{packed_path} -> {node:?}")?;
|
||||
|
||||
for i in CHILD_INDEX_RANGE.rev() {
|
||||
if state_mask.is_bit_set(i) {
|
||||
let mut child_path = path;
|
||||
child_path.push_unchecked(i);
|
||||
if let Some(child_node) = self.nodes_ref().get(&child_path) {
|
||||
stack.push((child_path, child_node, depth + 1));
|
||||
}
|
||||
for i in state_mask.iter().rev() {
|
||||
let mut child_path = path;
|
||||
child_path.push_unchecked(i);
|
||||
if let Some(child_node) = self.nodes_ref().get(&child_path) {
|
||||
stack.push((child_path, child_node, depth + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -503,16 +500,14 @@ impl SparseTrieTrait for SerialSparseTrie {
|
||||
self.nodes.insert(path, SparseNode::Empty);
|
||||
}
|
||||
TrieNode::Branch(branch) => {
|
||||
// For a branch node, iterate over all potential children
|
||||
// For a branch node, iterate over all children
|
||||
let mut stack_ptr = branch.as_ref().first_child_index();
|
||||
for idx in CHILD_INDEX_RANGE {
|
||||
if branch.state_mask.is_bit_set(idx) {
|
||||
let mut child_path = path;
|
||||
child_path.push_unchecked(idx);
|
||||
// Reveal each child node or hash it has
|
||||
self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
|
||||
stack_ptr += 1;
|
||||
}
|
||||
for idx in branch.state_mask.iter() {
|
||||
let mut child_path = path;
|
||||
child_path.push_unchecked(idx);
|
||||
// Reveal each child node or hash it has
|
||||
self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
|
||||
stack_ptr += 1;
|
||||
}
|
||||
// Update the branch node entry in the nodes map, handling cases where a blinded
|
||||
// node is now replaced with a revealed node.
|
||||
@@ -1500,12 +1495,10 @@ impl SerialSparseTrie {
|
||||
} else {
|
||||
unchanged_prefix_set.insert(path);
|
||||
|
||||
for bit in CHILD_INDEX_RANGE.rev() {
|
||||
if state_mask.is_bit_set(bit) {
|
||||
let mut child_path = path;
|
||||
child_path.push_unchecked(bit);
|
||||
paths.push((child_path, level + 1));
|
||||
}
|
||||
for bit in state_mask.iter().rev() {
|
||||
let mut child_path = path;
|
||||
child_path.push_unchecked(bit);
|
||||
paths.push((child_path, level + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1659,12 +1652,10 @@ impl SerialSparseTrie {
|
||||
buffers.branch_child_buf.clear();
|
||||
// Walk children in a reverse order from `f` to `0`, so we pop the `0` first
|
||||
// from the stack and keep walking in the sorted order.
|
||||
for bit in CHILD_INDEX_RANGE.rev() {
|
||||
if state_mask.is_bit_set(bit) {
|
||||
let mut child = path;
|
||||
child.push_unchecked(bit);
|
||||
buffers.branch_child_buf.push(child);
|
||||
}
|
||||
for bit in state_mask.iter().rev() {
|
||||
let mut child = path;
|
||||
child.push_unchecked(bit);
|
||||
buffers.branch_child_buf.push(child);
|
||||
}
|
||||
|
||||
buffers
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{BranchNodeCompact, Nibbles, StoredSubNode, CHILD_INDEX_RANGE};
|
||||
use crate::{BranchNodeCompact, Nibbles, StoredSubNode};
|
||||
use alloy_primitives::B256;
|
||||
use alloy_trie::proof::AddedRemovedKeys;
|
||||
|
||||
@@ -57,15 +57,12 @@ impl CursorSubNode {
|
||||
/// Creates a new [`CursorSubNode`] from a key and an optional node.
|
||||
pub fn new(key: Nibbles, node: Option<BranchNodeCompact>) -> Self {
|
||||
// Find the first nibble that is set in the state mask of the node.
|
||||
let position = node.as_ref().filter(|n| n.root_hash.is_none()).map_or(
|
||||
SubNodePosition::ParentBranch,
|
||||
|n| {
|
||||
let mut child_index_range = CHILD_INDEX_RANGE;
|
||||
SubNodePosition::Child(
|
||||
child_index_range.find(|i| n.state_mask.is_bit_set(*i)).unwrap(),
|
||||
)
|
||||
},
|
||||
);
|
||||
let position = node
|
||||
.as_ref()
|
||||
.filter(|n| n.root_hash.is_none())
|
||||
.map_or(SubNodePosition::ParentBranch, |n| {
|
||||
SubNodePosition::Child(n.state_mask.iter().next().unwrap())
|
||||
});
|
||||
Self::new_with_full_key(key, node, position)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user