diff --git a/Cargo.lock b/Cargo.lock index 22c9001e7d36..72c0bd3f7dea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5650,6 +5650,7 @@ dependencies = [ "rayon", "reth-db", "reth-interfaces", + "reth-metrics", "reth-primitives", "reth-provider", "reth-stages", diff --git a/bin/reth/src/node/mod.rs b/bin/reth/src/node/mod.rs index 3c3aa43165e5..184949c4cf6e 100644 --- a/bin/reth/src/node/mod.rs +++ b/bin/reth/src/node/mod.rs @@ -386,7 +386,6 @@ impl Command { db.clone(), self.chain.clone(), prune_config.block_interval, - tree_config.max_reorg_depth(), prune_config.parts, BatchSizes::default(), ) diff --git a/crates/consensus/beacon/src/engine/test_utils.rs b/crates/consensus/beacon/src/engine/test_utils.rs index 46fb5eaeb245..78b3825e6b39 100644 --- a/crates/consensus/beacon/src/engine/test_utils.rs +++ b/crates/consensus/beacon/src/engine/test_utils.rs @@ -469,7 +469,6 @@ where db.clone(), self.base_config.chain_spec.clone(), 5, - 0, PruneModes::default(), BatchSizes::default(), ); diff --git a/crates/prune/Cargo.toml b/crates/prune/Cargo.toml index 99a4901cb133..4ef111c6cda0 100644 --- a/crates/prune/Cargo.toml +++ b/crates/prune/Cargo.toml @@ -16,6 +16,7 @@ reth-primitives.workspace = true reth-db.workspace = true reth-provider.workspace = true reth-interfaces.workspace = true +reth-metrics.workspace = true # misc tracing.workspace = true diff --git a/crates/prune/src/lib.rs b/crates/prune/src/lib.rs index c7cb720cb696..b6264e47ceb3 100644 --- a/crates/prune/src/lib.rs +++ b/crates/prune/src/lib.rs @@ -1,5 +1,7 @@ mod error; +mod metrics; mod pruner; pub use error::PrunerError; +use metrics::Metrics; pub use pruner::{BatchSizes, Pruner, PrunerResult, PrunerWithResult}; diff --git a/crates/prune/src/metrics.rs b/crates/prune/src/metrics.rs new file mode 100644 index 000000000000..8c3e768f1435 --- /dev/null +++ b/crates/prune/src/metrics.rs @@ -0,0 +1,36 @@ +use reth_metrics::{metrics, metrics::Histogram, Metrics}; +use reth_primitives::PrunePart; +use std::collections::HashMap; + +#[derive(Debug, Default)] +pub(crate) struct Metrics { + pub(crate) pruner: PrunerMetrics, + prune_parts: HashMap, +} + +impl Metrics { + /// Returns existing or initializes a new instance of [PrunerPartMetrics] for the provided + /// [PrunePart]. + pub(crate) fn get_prune_part_metrics( + &mut self, + prune_part: PrunePart, + ) -> &mut PrunerPartMetrics { + self.prune_parts.entry(prune_part).or_insert_with(|| { + PrunerPartMetrics::new_with_labels(&[("part", prune_part.to_string())]) + }) + } +} + +#[derive(Metrics)] +#[metrics(scope = "pruner")] +pub(crate) struct PrunerMetrics { + /// Pruning duration + pub(crate) duration_seconds: Histogram, +} + +#[derive(Metrics)] +#[metrics(scope = "pruner.parts")] +pub(crate) struct PrunerPartMetrics { + /// Pruning duration for this part + pub(crate) duration_seconds: Histogram, +} diff --git a/crates/prune/src/pruner.rs b/crates/prune/src/pruner.rs index 4a50faf26842..3b8270bde8bf 100644 --- a/crates/prune/src/pruner.rs +++ b/crates/prune/src/pruner.rs @@ -1,6 +1,6 @@ //! Support for pruning. -use crate::PrunerError; +use crate::{Metrics, PrunerError}; use rayon::prelude::*; use reth_db::{database::Database, tables}; use reth_primitives::{ @@ -10,7 +10,7 @@ use reth_provider::{ BlockReader, DatabaseProviderRW, ProviderFactory, PruneCheckpointReader, PruneCheckpointWriter, TransactionsProvider, }; -use std::{ops::RangeInclusive, sync::Arc}; +use std::{ops::RangeInclusive, sync::Arc, time::Instant}; use tracing::{debug, instrument, trace}; /// Result of [Pruner::run] execution @@ -33,14 +33,11 @@ impl Default for BatchSizes { /// Pruning routine. Main pruning logic happens in [Pruner::run]. pub struct Pruner { + metrics: Metrics, provider_factory: ProviderFactory, /// Minimum pruning interval measured in blocks. All prune parts are checked and, if needed, /// pruned, when the chain advances by the specified number of blocks. min_block_interval: u64, - /// Maximum prune depth. Used to determine the pruning target for parts that are needed during - /// the reorg, e.g. changesets. - #[allow(dead_code)] - max_prune_depth: u64, /// Last pruned block number. Used in conjunction with `min_block_interval` to determine /// when the pruning needs to be initiated. last_pruned_block_number: Option, @@ -54,14 +51,13 @@ impl Pruner { db: DB, chain_spec: Arc, min_block_interval: u64, - max_prune_depth: u64, modes: PruneModes, batch_sizes: BatchSizes, ) -> Self { Self { + metrics: Metrics::default(), provider_factory: ProviderFactory::new(db, chain_spec), min_block_interval, - max_prune_depth, last_pruned_block_number: None, modes, batch_sizes, @@ -70,29 +66,48 @@ impl Pruner { /// Run the pruner pub fn run(&mut self, tip_block_number: BlockNumber) -> PrunerResult { + let start = Instant::now(); + let provider = self.provider_factory.provider_rw()?; if let Some((to_block, prune_mode)) = self.modes.prune_target_block_receipts(tip_block_number)? { + let part_start = Instant::now(); self.prune_receipts(&provider, to_block, prune_mode)?; + self.metrics + .get_prune_part_metrics(PrunePart::Receipts) + .duration_seconds + .record(part_start.elapsed()) } if let Some((to_block, prune_mode)) = self.modes.prune_target_block_transaction_lookup(tip_block_number)? { + let part_start = Instant::now(); self.prune_transaction_lookup(&provider, to_block, prune_mode)?; + self.metrics + .get_prune_part_metrics(PrunePart::TransactionLookup) + .duration_seconds + .record(part_start.elapsed()) } if let Some((to_block, prune_mode)) = self.modes.prune_target_block_sender_recovery(tip_block_number)? { + let part_start = Instant::now(); self.prune_transaction_senders(&provider, to_block, prune_mode)?; + self.metrics + .get_prune_part_metrics(PrunePart::SenderRecovery) + .duration_seconds + .record(part_start.elapsed()) } provider.commit()?; - self.last_pruned_block_number = Some(tip_block_number); + + self.metrics.pruner.duration_seconds.record(start.elapsed()); + Ok(()) } @@ -323,7 +338,7 @@ mod tests { fn is_pruning_needed() { let db = create_test_rw_db(); let pruner = - Pruner::new(db, MAINNET.clone(), 5, 0, PruneModes::default(), BatchSizes::default()); + Pruner::new(db, MAINNET.clone(), 5, PruneModes::default(), BatchSizes::default()); // No last pruned block number was set before let first_block_number = 1; @@ -370,7 +385,6 @@ mod tests { tx.inner_raw(), MAINNET.clone(), 5, - 0, PruneModes { receipts: Some(prune_mode), ..Default::default() }, BatchSizes { // Less than total amount of blocks to prune to test the batching logic @@ -431,7 +445,6 @@ mod tests { tx.inner_raw(), MAINNET.clone(), 5, - 0, PruneModes { transaction_lookup: Some(prune_mode), ..Default::default() }, BatchSizes { // Less than total amount of blocks to prune to test the batching logic @@ -498,7 +511,6 @@ mod tests { tx.inner_raw(), MAINNET.clone(), 5, - 0, PruneModes { sender_recovery: Some(prune_mode), ..Default::default() }, BatchSizes { // Less than total amount of blocks to prune to test the batching logic