Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
91 changes: 21 additions & 70 deletions crates/engine/tree/src/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,40 +228,6 @@ impl OnStateHook for MeteredStateHook {
}
}

/// Helper function to update block timing metrics for insert phase.
///
/// This function handles the common pattern of:
/// 1. Getting existing timing metrics (if block was built locally)
/// 2. Creating new metrics (if block was received from network)
/// 3. Setting insert timing values
/// 4. Calculating total as the sum of validate_and_execute + insert_to_tree
/// 5. Storing the updated metrics
fn update_insert_timing_metrics(
block_hash: B256,
validate_and_execute: std::time::Duration,
insert_to_tree: std::time::Duration,
) {
use reth_node_metrics::block_timing::{
get_block_timing, store_block_timing, BlockTimingMetrics,
};

let mut timing_metrics = if let Some(existing) = get_block_timing(&block_hash) {
// Block was built locally, update insert timing
existing
} else {
// Block was received from network, create timing metrics with insert timing only
BlockTimingMetrics::default()
};

timing_metrics.insert.validate_and_execute = validate_and_execute;
timing_metrics.insert.insert_to_tree = insert_to_tree;
// Total should be the sum of validate_and_execute + insert_to_tree
timing_metrics.insert.total =
timing_metrics.insert.validate_and_execute + timing_metrics.insert.insert_to_tree;

store_block_timing(block_hash, timing_metrics);
}

/// The engine API tree handler implementation.
///
/// This type is responsible for processing engine API requests, maintaining the canonical state and
Expand Down Expand Up @@ -1427,17 +1393,6 @@ where
self.metrics.engine.inserted_already_executed_blocks.increment(1);
let elapsed = now.elapsed();

// X Layer: Update timing metrics for InsertExecutedBlock path
// Note: validate_exec time is 0 because block was already executed during
// build
use std::time::Duration;
let block_hash = block.recovered_block().hash();
update_insert_timing_metrics(
block_hash,
Duration::from_nanos(0),
insert_tree_elapsed,
);

self.emit_event(EngineApiEvent::BeaconConsensus(
ConsensusEngineEvent::CanonicalBlockAdded(block, elapsed),
));
Expand Down Expand Up @@ -2500,20 +2455,6 @@ where
// run the conversion to ensure that the block hash is valid.
convert_to_block(self, input)?;

// X Layer: Even if block is already seen, update timing metrics if it was built
// locally Block was built locally but already exists in tree
// Set insert timing to 0 for now, will be updated in event handler if elapsed > 0
use reth_node_metrics::block_timing::get_block_timing;
use std::time::Duration;
let block_hash = block_num_hash.hash;
if get_block_timing(&block_hash).is_some() {
update_insert_timing_metrics(
block_hash,
Duration::from_nanos(0),
Duration::from_nanos(0),
);
}

return Ok(InsertPayloadOk::AlreadySeen(BlockStatus::Valid))
}
_ => {}
Expand Down Expand Up @@ -2558,12 +2499,21 @@ where

let ctx = TreeCtx::new(&mut self.state, &self.canonical_in_memory_state);

// X Layer: Track insert timing
let validate_exec_start = Instant::now();
// X Layer: Track insert timing with RAII
let start = Instant::now();

let executed = execute(&mut self.payload_validator, input, ctx)?;
let validate_exec_elapsed = validate_exec_start.elapsed();
let block_hash = block_num_hash.hash;

// Create timing context with Prometheus support
// We'll create Prometheus metrics from the handler's metrics if needed
use reth_node_metrics::block_timing::{BlockTimingContext, BlockTimingPrometheusMetrics};
let prom_metrics = BlockTimingPrometheusMetrics::default();
let mut timing_ctx = BlockTimingContext::new_with_prometheus(block_hash, prom_metrics);

// validate and execute
let executed = {
let _guard = timing_ctx.time_validate_and_execute();
execute(&mut self.payload_validator, input, ctx)?
};

// if the parent is the canonical head, we can insert the block as the pending block
if self.state.tree_state.canonical_block_hash() == executed.recovered_block().parent_hash()
Expand All @@ -2572,17 +2522,18 @@ where
self.canonical_in_memory_state.set_pending_block(executed.clone());
}

let insert_tree_start = Instant::now();
self.state.tree_state.insert_executed(executed.clone());
let insert_tree_elapsed = insert_tree_start.elapsed();
// insert to tree
{
let _guard = timing_ctx.time_insert_to_tree();
self.state.tree_state.insert_executed(executed.clone());
}
self.metrics.engine.executed_blocks.set(self.state.tree_state.block_count() as f64);

// emit insert event
let elapsed = start.elapsed();

// X Layer: Update timing metrics with insert timing
let block_hash = executed.recovered_block().hash();
update_insert_timing_metrics(block_hash, validate_exec_elapsed, insert_tree_elapsed);
// X Layer: Update timing metrics (auto-updates and stores on drop)
timing_ctx.update_totals();
let engine_event = if is_fork {
ConsensusEngineEvent::ForkBlockAdded(executed.clone(), elapsed)
} else {
Expand Down
Loading