Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(trie): metrics #6943

Merged
merged 8 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions crates/trie/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ reth-interfaces.workspace = true
reth-db.workspace = true
revm.workspace = true

# metrics
reth-metrics.workspace = true
metrics.workspace = true

# alloy
alloy-rlp.workspace = true
alloy-chains.workspace = true
Expand Down
2 changes: 2 additions & 0 deletions crates/trie/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ pub mod updates;
mod progress;
pub use progress::{IntermediateStateRootState, StateRootProgress};

mod metrics;

/// Collection of trie-related test utilities.
#[cfg(any(test, feature = "test-utils"))]
pub mod test_utils;
69 changes: 69 additions & 0 deletions crates/trie/src/metrics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use metrics::Histogram;
use reth_metrics::Metrics;
use std::time::Instant;

#[derive(Metrics)]
#[metrics(scope = "trie")]
pub(crate) struct TrieRootMetrics {
/// The number of microseconds trie root calculation lasted.
duration_micros: Histogram,
/// The number of branches added during trie root calculation.
branches_added: Histogram,
/// The number of leaves added during trie root calculation.
leaves_added: Histogram,
shekhirin marked this conversation as resolved.
Show resolved Hide resolved
}

impl TrieRootMetrics {
pub(crate) fn new(ty: TrieType) -> Self {
Self::new_with_labels(&[("type", ty.as_str())])
Copy link
Collaborator

@shekhirin shekhirin Mar 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally, we should cache this initialization, see #6730.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#6730 was impactful because metrics initialization was on a hot code path. not the case here, so i wouldn't worry too much

}

pub(crate) fn record(&self, tracker: TrieTracker) {
self.duration_micros.record(tracker.started_at.elapsed().as_millis() as f64);
rkrasiuk marked this conversation as resolved.
Show resolved Hide resolved
self.branches_added.record(tracker.branches_added as f64);
self.leaves_added.record(tracker.leaves_added as f64);
}
}

/// Trie type for differentiating between various trie calculations.
#[derive(Clone, Copy, Debug)]
pub(crate) enum TrieType {
State,
Storage,
}

impl TrieType {
pub(crate) const fn as_str(&self) -> &'static str {
match self {
Self::State => "state",
Self::Storage => "storage",
}
}
}

#[derive(Clone, Copy, Debug)]
pub(crate) struct TrieTracker {
started_at: Instant,
branches_added: u64,
leaves_added: u64,
}

impl Default for TrieTracker {
fn default() -> Self {
Self { started_at: Instant::now(), branches_added: 0, leaves_added: 0 }
}
}

impl TrieTracker {
pub(crate) fn leaves_added(&self) -> u64 {
self.leaves_added
}

pub(crate) fn inc_branch(&mut self) {
self.branches_added += 1;
}

pub(crate) fn inc_leaf(&mut self) {
self.leaves_added += 1;
}
}
24 changes: 22 additions & 2 deletions crates/trie/src/trie.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
hashed_cursor::{HashedCursorFactory, HashedStorageCursor},
metrics::{TrieRootMetrics, TrieTracker, TrieType},
node_iter::{AccountNode, AccountNodeIter, StorageNode, StorageNodeIter},
prefix_set::{PrefixSet, PrefixSetLoader, PrefixSetMut, TriePrefixSets},
progress::{IntermediateStateRootState, StateRootProgress},
Expand Down Expand Up @@ -32,6 +33,8 @@ pub struct StateRoot<T, H> {
previous_state: Option<IntermediateStateRootState>,
/// The number of updates after which the intermediate progress should be returned.
threshold: u64,
/// State root metrics.
metrics: TrieRootMetrics,
}

impl<T, H> StateRoot<T, H> {
Expand Down Expand Up @@ -67,6 +70,7 @@ impl<T, H> StateRoot<T, H> {
prefix_sets: self.prefix_sets,
threshold: self.threshold,
previous_state: self.previous_state,
metrics: self.metrics,
}
}

Expand All @@ -78,6 +82,7 @@ impl<T, H> StateRoot<T, H> {
prefix_sets: self.prefix_sets,
threshold: self.threshold,
previous_state: self.previous_state,
metrics: self.metrics,
}
}
}
Expand All @@ -91,6 +96,7 @@ impl<'a, TX: DbTx> StateRoot<&'a TX, &'a TX> {
prefix_sets: TriePrefixSets::default(),
previous_state: None,
threshold: 100_000,
metrics: TrieRootMetrics::new(TrieType::State),
}
}

Expand Down Expand Up @@ -198,6 +204,7 @@ where

fn calculate(self, retain_updates: bool) -> Result<StateRootProgress, StateRootError> {
trace!(target: "trie::loader", "calculating state root");
let mut tracker = TrieTracker::default();
let mut trie_updates = TrieUpdates::default();

let hashed_account_cursor = self.hashed_cursor_factory.hashed_account_cursor()?;
Expand Down Expand Up @@ -230,9 +237,11 @@ where
while let Some(node) = account_node_iter.try_next()? {
match node {
AccountNode::Branch(node) => {
tracker.inc_branch();
hash_builder.add_branch(node.key, node.value, node.children_are_in_trie);
}
AccountNode::Leaf(hashed_address, account) => {
tracker.inc_leaf();
hashed_entries_walked += 1;

// We assume we can always calculate a storage root without
Expand Down Expand Up @@ -310,6 +319,7 @@ where
self.prefix_sets.destroyed_accounts.into_iter().map(TrieKey::StorageTrie),
);

self.metrics.record(tracker);
Ok(StateRootProgress::Complete(root, hashed_entries_walked, trie_updates))
}
}
Expand All @@ -325,6 +335,8 @@ pub struct StorageRoot<T, H> {
pub hashed_address: B256,
/// The set of storage slot prefixes that have changed.
pub prefix_set: PrefixSet,
/// Storage root metrics.
metrics: TrieRootMetrics,
}

impl<T, H> StorageRoot<T, H> {
Expand All @@ -344,6 +356,7 @@ impl<T, H> StorageRoot<T, H> {
hashed_cursor_factory,
hashed_address,
prefix_set: PrefixSetMut::default().freeze(),
metrics: TrieRootMetrics::new(TrieType::Storage),
}
}

Expand All @@ -360,6 +373,7 @@ impl<T, H> StorageRoot<T, H> {
hashed_cursor_factory,
hashed_address: self.hashed_address,
prefix_set: self.prefix_set,
metrics: self.metrics,
}
}

Expand All @@ -370,6 +384,7 @@ impl<T, H> StorageRoot<T, H> {
hashed_cursor_factory: self.hashed_cursor_factory,
hashed_address: self.hashed_address,
prefix_set: self.prefix_set,
metrics: self.metrics,
}
}
}
Expand Down Expand Up @@ -415,6 +430,7 @@ where
retain_updates: bool,
) -> Result<(B256, usize, TrieUpdates), StorageRootError> {
trace!(target: "trie::storage_root", hashed_address = ?self.hashed_address, "calculating storage root");

let mut hashed_storage_cursor = self.hashed_cursor_factory.hashed_storage_cursor()?;

// short circuit on empty storage
Expand All @@ -426,21 +442,22 @@ where
))
}

let mut tracker = TrieTracker::default();
let trie_cursor = self.trie_cursor_factory.storage_tries_cursor(self.hashed_address)?;
let walker = TrieWalker::new(trie_cursor, self.prefix_set).with_updates(retain_updates);

let mut hash_builder = HashBuilder::default().with_updates(retain_updates);

let mut storage_slots_walked = 0;
let mut storage_node_iter =
StorageNodeIter::new(walker, hashed_storage_cursor, self.hashed_address);
while let Some(node) = storage_node_iter.try_next()? {
match node {
StorageNode::Branch(node) => {
tracker.inc_branch();
hash_builder.add_branch(node.key, node.value, node.children_are_in_trie);
}
StorageNode::Leaf(hashed_slot, value) => {
storage_slots_walked += 1;
tracker.inc_leaf();
hash_builder.add_leaf(
Nibbles::unpack(hashed_slot),
alloy_rlp::encode_fixed_size(&value).as_ref(),
Expand All @@ -458,7 +475,10 @@ where
trie_updates.extend(walker_updates);
trie_updates.extend_with_storage_updates(self.hashed_address, hash_builder_updates);

self.metrics.record(tracker);
trace!(target: "trie::storage_root", ?root, hashed_address = ?self.hashed_address, "calculated storage root");

let storage_slots_walked = tracker.leaves_added() as usize;
Ok((root, storage_slots_walked, trie_updates))
}
}
Expand Down
Loading