Skip to content

Commit 3bebb0a

Browse files
authored
chore: add metrics on redundant proof nodes (#14969)
1 parent a38c991 commit 3bebb0a

File tree

5 files changed

+97
-0
lines changed

5 files changed

+97
-0
lines changed

Cargo.lock

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/trie/sparse/Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ alloy-rlp.workspace = true
2626
smallvec = { workspace = true, features = ["const_new"] }
2727
thiserror.workspace = true
2828

29+
# metrics
30+
reth-metrics.workspace = true
31+
metrics.workspace = true
32+
2933
[dev-dependencies]
3034
reth-primitives-traits = { workspace = true, features = ["arbitrary"] }
3135
reth-provider = { workspace = true, features = ["test-utils"] }

crates/trie/sparse/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ pub use trie::*;
88

99
pub mod blinded;
1010

11+
mod metrics;
12+
1113
/// Re-export sparse trie error types.
1214
pub mod errors {
1315
pub use reth_execution_errors::{

crates/trie/sparse/src/metrics.rs

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//! Metrics for the sparse state trie
2+
3+
use reth_metrics::{metrics::Histogram, Metrics};
4+
5+
/// Metrics for the sparse state trie
6+
#[derive(Default, Debug)]
7+
pub(crate) struct SparseStateTrieMetrics {
8+
/// Number of account nodes that were skipped during a multiproof reveal due to being redundant
9+
/// (i.e. they were already revealed)
10+
pub(crate) multiproof_skipped_account_nodes: u64,
11+
/// Number of total account nodes, including those that were skipped.
12+
pub(crate) multiproof_total_account_nodes: u64,
13+
/// Number of storage nodes that were skipped during a multiproof reveal due to being redundant
14+
/// (i.e. they were already revealed)
15+
pub(crate) multiproof_skipped_storage_nodes: u64,
16+
/// Number of total storage nodes, including those that were skipped.
17+
pub(crate) multiproof_total_storage_nodes: u64,
18+
/// The actual metrics we will record into the histogram
19+
pub(crate) histograms: SparseStateTrieHistograms,
20+
}
21+
22+
impl SparseStateTrieMetrics {
23+
/// Record the metrics into the histograms
24+
pub(crate) fn record(&self) {
25+
self.histograms
26+
.multiproof_skipped_account_nodes
27+
.record(self.multiproof_skipped_account_nodes as f64);
28+
self.histograms
29+
.multiproof_total_account_nodes
30+
.record(self.multiproof_total_account_nodes as f64);
31+
self.histograms
32+
.multiproof_skipped_storage_nodes
33+
.record(self.multiproof_skipped_storage_nodes as f64);
34+
self.histograms
35+
.multiproof_total_storage_nodes
36+
.record(self.multiproof_total_storage_nodes as f64);
37+
}
38+
39+
/// Increment the skipped account nodes counter
40+
pub(crate) fn increment_skipped_account_nodes(&mut self) {
41+
self.multiproof_skipped_account_nodes += 1;
42+
}
43+
44+
/// Increment the total account nodes counter
45+
pub(crate) fn increment_total_account_nodes(&mut self) {
46+
self.multiproof_total_account_nodes += 1;
47+
}
48+
49+
/// Increment the skipped storage nodes counter
50+
pub(crate) fn increment_skipped_storage_nodes(&mut self) {
51+
self.multiproof_skipped_storage_nodes += 1;
52+
}
53+
54+
/// Increment the total storage nodes counter
55+
pub(crate) fn increment_total_storage_nodes(&mut self) {
56+
self.multiproof_total_storage_nodes += 1;
57+
}
58+
}
59+
60+
/// Metrics for the sparse state trie
61+
#[derive(Metrics)]
62+
#[metrics(scope = "sparse_state_trie")]
63+
pub(crate) struct SparseStateTrieHistograms {
64+
/// Histogram of account nodes that were skipped during a multiproof reveal due to being
65+
/// redundant (i.e. they were already revealed)
66+
pub(crate) multiproof_skipped_account_nodes: Histogram,
67+
/// Histogram of total account nodes, including those that were skipped.
68+
pub(crate) multiproof_total_account_nodes: Histogram,
69+
/// Histogram of storage nodes that were skipped during a multiproof reveal due to being
70+
/// redundant (i.e. they were already revealed)
71+
pub(crate) multiproof_skipped_storage_nodes: Histogram,
72+
/// Histogram of total storage nodes, including those that were skipped.
73+
pub(crate) multiproof_total_storage_nodes: Histogram,
74+
}

crates/trie/sparse/src/state.rs

+15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::{
22
blinded::{BlindedProvider, BlindedProviderFactory, DefaultBlindedProviderFactory},
3+
metrics::SparseStateTrieMetrics,
34
RevealedSparseTrie, SparseTrie, TrieMasks,
45
};
56
use alloy_primitives::{
@@ -34,6 +35,8 @@ pub struct SparseStateTrie<F: BlindedProviderFactory = DefaultBlindedProviderFac
3435
retain_updates: bool,
3536
/// Reusable buffer for RLP encoding of trie accounts.
3637
account_rlp_buf: Vec<u8>,
38+
/// Metrics for the sparse state trie.
39+
metrics: SparseStateTrieMetrics,
3740
}
3841

3942
impl Default for SparseStateTrie {
@@ -46,6 +49,7 @@ impl Default for SparseStateTrie {
4649
revealed_storage_paths: Default::default(),
4750
retain_updates: false,
4851
account_rlp_buf: Vec::with_capacity(TRIE_ACCOUNT_RLP_MAX_SIZE),
52+
metrics: Default::default(),
4953
}
5054
}
5155
}
@@ -81,6 +85,7 @@ impl<F: BlindedProviderFactory> SparseStateTrie<F> {
8185
revealed_storage_paths: Default::default(),
8286
retain_updates: false,
8387
account_rlp_buf: Vec::with_capacity(TRIE_ACCOUNT_RLP_MAX_SIZE),
88+
metrics: Default::default(),
8489
}
8590
}
8691

@@ -260,8 +265,10 @@ impl<F: BlindedProviderFactory> SparseStateTrie<F> {
260265

261266
// Reveal the remaining proof nodes.
262267
for (path, bytes) in account_nodes {
268+
self.metrics.increment_total_account_nodes();
263269
// If the node is already revealed, skip it.
264270
if self.revealed_account_paths.contains(&path) {
271+
self.metrics.increment_skipped_account_nodes();
265272
continue
266273
}
267274
let node = TrieNode::decode(&mut &bytes[..])?;
@@ -307,8 +314,10 @@ impl<F: BlindedProviderFactory> SparseStateTrie<F> {
307314

308315
// Reveal the remaining proof nodes.
309316
for (path, bytes) in nodes {
317+
self.metrics.increment_total_storage_nodes();
310318
// If the node is already revealed, skip it.
311319
if revealed_nodes.contains(&path) {
320+
self.metrics.increment_skipped_storage_nodes();
312321
continue
313322
}
314323
let node = TrieNode::decode(&mut &bytes[..])?;
@@ -521,11 +530,17 @@ impl<F: BlindedProviderFactory> SparseStateTrie<F> {
521530
///
522531
/// If the trie has not been revealed, this function reveals the root node and returns its hash.
523532
pub fn root(&mut self) -> SparseStateTrieResult<B256> {
533+
// record revealed node metrics
534+
self.metrics.record();
535+
524536
Ok(self.revealed_trie_mut()?.root())
525537
}
526538

527539
/// Returns sparse trie root and trie updates if the trie has been revealed.
528540
pub fn root_with_updates(&mut self) -> SparseStateTrieResult<(B256, TrieUpdates)> {
541+
// record revealed node metrics
542+
self.metrics.record();
543+
529544
let storage_tries = self.storage_trie_updates();
530545
let revealed = self.revealed_trie_mut()?;
531546

0 commit comments

Comments
 (0)