Compare commits

...

3 Commits

Author SHA1 Message Date
Georgios Konstantopoulos
30c26e87e6 fix: backtick gas_used in doc comments for clippy
Amp-Thread-ID: https://ampcode.com/threads/T-019c4ccd-a73d-76af-972a-8e2072e994c1
Co-authored-by: Amp <amp@ampcode.com>
2026-02-11 14:49:29 +00:00
Georgios Konstantopoulos
0542325d9d docs: add changelog for gas-range measurement filter
Amp-Thread-ID: https://ampcode.com/threads/T-019c4ccd-a73d-76af-972a-8e2072e994c1
Co-authored-by: Amp <amp@ampcode.com>
2026-02-11 14:40:28 +00:00
Georgios Konstantopoulos
15966f2cf7 feat(reth-bench): add gas-range measurement filter for small blocks benchmarking
Adds --measure-gas-min and --measure-gas-max flags to reth-bench new-payload-fcu
and reth-bench-compare. All blocks still execute sequentially for state continuity,
but only blocks within the specified gas range are included in benchmark timing and
statistics.

This enables focused benchmarking of small blocks (0-20M gas) to identify tuning
opportunities for typical mainnet block sizes.

Amp-Thread-ID: https://ampcode.com/threads/T-019c4ccd-a73d-76af-972a-8e2072e994c1
Co-authored-by: Amp <amp@ampcode.com>
2026-02-11 13:15:36 +00:00
4 changed files with 75 additions and 9 deletions

View File

@@ -0,0 +1,6 @@
---
reth-bench-compare: minor
reth-bench: minor
---
Added gas range filtering for benchmark measurements. Blocks with gas usage outside the specified `--measure-gas-min` and `--measure-gas-max` range are now executed but excluded from timing statistics, allowing more focused performance analysis of blocks within specific gas usage ranges.

View File

@@ -21,6 +21,8 @@ pub(crate) struct BenchmarkRunner {
wait_for_persistence: bool,
persistence_threshold: Option<u64>,
warmup_blocks: u64,
measure_gas_min: Option<String>,
measure_gas_max: Option<String>,
}
impl BenchmarkRunner {
@@ -33,6 +35,8 @@ impl BenchmarkRunner {
wait_for_persistence: args.wait_for_persistence,
persistence_threshold: args.persistence_threshold,
warmup_blocks: args.get_warmup_blocks(),
measure_gas_min: args.measure_gas_min.clone(),
measure_gas_max: args.measure_gas_max.clone(),
}
}
@@ -103,6 +107,13 @@ impl BenchmarkRunner {
"--wait-time=0ms", // Warmup should avoid persistence waits.
]);
if let Some(ref gas_min) = self.measure_gas_min {
cmd.args(["--measure-gas-min", gas_min]);
}
if let Some(ref gas_max) = self.measure_gas_max {
cmd.args(["--measure-gas-max", gas_max]);
}
cmd.env("RUST_LOG_STYLE", "never")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
@@ -186,6 +197,13 @@ impl BenchmarkRunner {
&output_dir.to_string_lossy(),
]);
if let Some(ref gas_min) = self.measure_gas_min {
cmd.args(["--measure-gas-min", gas_min]);
}
if let Some(ref gas_max) = self.measure_gas_max {
cmd.args(["--measure-gas-max", gas_max]);
}
// Configure wait mode: both can be used together
// When both are set: wait at least wait_time, and also wait for persistence if needed
if let Some(ref wait_time) = self.wait_time {

View File

@@ -140,6 +140,18 @@ pub(crate) struct Args {
#[arg(long, value_name = "PERSISTENCE_THRESHOLD")]
pub persistence_threshold: Option<u64>,
/// Minimum `gas_used` for a block to be included in benchmark measurements.
/// Blocks below this threshold are still executed but excluded from timing stats.
/// Accepts short notation: K for thousand, M for million, G for billion.
#[arg(long, value_name = "GAS")]
pub measure_gas_min: Option<String>,
/// Maximum `gas_used` for a block to be included in benchmark measurements.
/// Blocks above this threshold are still executed but excluded from timing stats.
/// Accepts short notation: K for thousand, M for million, G for billion.
#[arg(long, value_name = "GAS")]
pub measure_gas_max: Option<String>,
/// Number of blocks to run for cache warmup after clearing caches.
/// If not specified, defaults to the same as --blocks
#[arg(long, value_name = "N")]

View File

@@ -12,7 +12,7 @@
use crate::{
bench::{
context::BenchContext,
helpers::parse_duration,
helpers::{parse_duration, parse_gas_limit},
output::{
write_benchmark_results, CombinedResult, NewPayloadResult, TotalGasOutput, TotalGasRow,
},
@@ -92,6 +92,12 @@ pub struct Command {
)]
rpc_block_buffer_size: usize,
#[arg(long, value_name = "GAS", value_parser = parse_gas_limit)]
measure_gas_min: Option<u64>,
#[arg(long, value_name = "GAS", value_parser = parse_gas_limit)]
measure_gas_max: Option<u64>,
#[command(flatten)]
benchmark: BenchmarkArgs,
}
@@ -205,7 +211,11 @@ impl Command {
}
});
let measure_gas_min = self.measure_gas_min.unwrap_or(0);
let measure_gas_max = self.measure_gas_max.unwrap_or(u64::MAX);
let mut results = Vec::new();
let mut total_blocks = 0u64;
let total_benchmark_duration = Instant::now();
let mut total_wait_time = Duration::ZERO;
@@ -247,18 +257,37 @@ impl Command {
total_latency,
};
// Exclude time spent waiting on the block prefetch channel from the benchmark duration.
// We want to measure engine throughput, not RPC fetch latency.
let current_duration = total_benchmark_duration.elapsed() - total_wait_time;
info!(target: "reth-bench", %combined_result);
total_blocks += 1;
if let Some(w) = &mut waiter {
w.on_block(block_number).await?;
}
let gas_row =
TotalGasRow { block_number, transaction_count, gas_used, time: current_duration };
results.push((gas_row, combined_result));
let in_measurement_range = gas_used >= measure_gas_min && gas_used <= measure_gas_max;
if in_measurement_range {
// Exclude time spent waiting on the block prefetch channel from the benchmark
// duration. We want to measure engine throughput, not RPC fetch latency.
let current_duration = total_benchmark_duration.elapsed() - total_wait_time;
info!(target: "reth-bench", %combined_result);
let gas_row = TotalGasRow {
block_number,
transaction_count,
gas_used,
time: current_duration,
};
results.push((gas_row, combined_result));
} else {
debug!(
target: "reth-bench",
?block_number,
gas_used,
measure_gas_min,
measure_gas_max,
"Skipping block from measurements (gas_used outside range)"
);
}
}
// Check if the spawned task encountered an error
@@ -285,7 +314,8 @@ impl Command {
total_gas_used = gas_output.total_gas_used,
total_duration = ?gas_output.total_duration,
execution_duration = ?gas_output.execution_duration,
blocks_processed = gas_output.blocks_processed,
blocks_measured = gas_output.blocks_processed,
blocks_processed = total_blocks,
wall_clock_ggas_per_second = format_args!("{:.4}", gas_output.total_gigagas_per_second()),
execution_ggas_per_second = format_args!("{:.4}", gas_output.execution_gigagas_per_second()),
"Benchmark complete"