|
1 | 1 | //! Benchmarks for historic scanning mode. |
2 | 2 | //! |
3 | | -//! Heavy load tests that measure the time to fetch all expected events. |
| 3 | +//! Heavy load tests that measure the time to fetch events from different block ranges. |
| 4 | +//! Uses pre-generated Anvil state dumps for fast, reproducible setup. |
| 5 | +//! |
| 6 | +//! Benchmarks three block ranges from a 100k event dump: |
| 7 | +//! - First 1/10 of blocks (~10k events) |
| 8 | +//! - First 1/2 of blocks (~50k events) |
| 9 | +//! - All blocks (100k events) |
4 | 10 |
|
| 11 | +use std::path::{Path, PathBuf}; |
5 | 12 | use std::sync::OnceLock; |
6 | 13 |
|
7 | 14 | use anyhow::{Result, bail}; |
8 | 15 | use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; |
9 | 16 | use event_scanner::{EventFilter, EventScannerBuilder, Message}; |
10 | | -use event_scanner_benches::{ |
11 | | - BenchConfig, BenchEnvironment, count_increased_signature, setup_environment, |
12 | | -}; |
| 17 | +use event_scanner_benches::{BenchEnvironment, count_increased_signature, setup_from_dump}; |
13 | 18 | use tokio_stream::StreamExt; |
14 | 19 |
|
| 20 | +/// Returns the path to the dump file, resolved from the crate's manifest directory. |
| 21 | +fn dump_path() -> PathBuf { |
| 22 | + Path::new(env!("CARGO_MANIFEST_DIR")).join("dumps/state_100000.json.gz") |
| 23 | +} |
| 24 | + |
15 | 25 | static RUNTIME: OnceLock<tokio::runtime::Runtime> = OnceLock::new(); |
16 | 26 |
|
17 | 27 | fn get_runtime() -> &'static tokio::runtime::Runtime { |
18 | 28 | RUNTIME.get_or_init(|| tokio::runtime::Runtime::new().expect("failed to create tokio runtime")) |
19 | 29 | } |
20 | 30 |
|
21 | | -/// Runs a single historic scan. |
| 31 | +/// Runs a historic scan for a specific block range. |
22 | 32 | /// |
23 | | -/// This fetches ALL events from block 0 to latest. |
24 | | -async fn run_historic_scan(env: &BenchEnvironment) -> Result<()> { |
| 33 | +/// Fetches events from block 0 to `to_block`. |
| 34 | +async fn run_historic_scan(env: &BenchEnvironment, to_block: u64) -> Result<()> { |
25 | 35 | let filter = EventFilter::new() |
26 | 36 | .contract_address(env.contract_address) |
27 | 37 | .event(count_increased_signature()); |
28 | 38 |
|
29 | 39 | let mut scanner = EventScannerBuilder::historic() |
30 | 40 | .max_block_range(100) |
31 | 41 | .from_block(0) |
32 | | - .to_block(alloy::eips::BlockNumberOrTag::Latest) |
| 42 | + .to_block(to_block) |
33 | 43 | .connect(env.provider.clone()) |
34 | 44 | .await?; |
35 | 45 |
|
@@ -58,26 +68,40 @@ fn historic_scanning_benchmark(c: &mut Criterion) { |
58 | 68 |
|
59 | 69 | // Configure for heavy load tests |
60 | 70 | group.warm_up_time(std::time::Duration::from_secs(5)); |
61 | | - group.measurement_time(std::time::Duration::from_secs(120)); |
62 | | - |
63 | | - // Heavy load test: 100,000 events |
64 | | - // Also include smaller sizes for regression comparison |
65 | | - for event_count in [10_000, 50_000, 100_000] { |
66 | | - println!("Setting up environment with {event_count} events..."); |
67 | | - |
68 | | - // Setup environment once per event count (events are pre-generated) |
69 | | - let env: BenchEnvironment = rt.block_on(async { |
70 | | - let config = BenchConfig::new(event_count); |
71 | | - setup_environment(config).await.expect("failed to setup benchmark environment") |
72 | | - }); |
73 | | - |
74 | | - println!("Environment ready. Starting benchmark..."); |
75 | | - |
76 | | - group.throughput(Throughput::Elements(event_count as u64)); |
77 | | - |
78 | | - group.bench_with_input(BenchmarkId::new("events", event_count), &env, |b, env| { |
79 | | - b.to_async(&rt) |
80 | | - .iter(|| async { run_historic_scan(env).await.expect("historic scan failed") }); |
| 71 | + group.measurement_time(std::time::Duration::from_secs(140)); |
| 72 | + |
| 73 | + // Load environment from pre-generated dump (100k events) |
| 74 | + println!("Loading benchmark environment from dump file..."); |
| 75 | + let env: BenchEnvironment = rt.block_on(async { |
| 76 | + setup_from_dump(&dump_path()).await.expect("failed to load benchmark environment from dump") |
| 77 | + }); |
| 78 | + println!( |
| 79 | + "Environment ready: {} events across {} blocks at contract {}", |
| 80 | + env.event_count, env.block_number, env.contract_address |
| 81 | + ); |
| 82 | + |
| 83 | + // Calculate block ranges: |
| 84 | + // - 1/10 of blocks: ~10k events |
| 85 | + // - 1/2 of blocks: ~50k events |
| 86 | + // - All blocks: 100k events |
| 87 | + let total_blocks = env.block_number; |
| 88 | + let block_ranges = [ |
| 89 | + (total_blocks / 10, "1/10 blocks (~10k events)"), |
| 90 | + (total_blocks / 2, "1/2 blocks (~50k events)"), |
| 91 | + (total_blocks, "all blocks (100k events)"), |
| 92 | + ]; |
| 93 | + |
| 94 | + for (to_block, description) in block_ranges { |
| 95 | + println!("Benchmarking historic scan: {description} (to block {to_block})..."); |
| 96 | + |
| 97 | + // Estimate events based on block ratio (events are roughly evenly distributed) |
| 98 | + let estimated_events = (env.event_count as u64 * to_block) / total_blocks; |
| 99 | + group.throughput(Throughput::Elements(estimated_events)); |
| 100 | + |
| 101 | + group.bench_with_input(BenchmarkId::new("blocks", to_block), &to_block, |b, &to_block| { |
| 102 | + b.to_async(rt).iter(|| async { |
| 103 | + run_historic_scan(&env, to_block).await.expect("historic scan failed"); |
| 104 | + }); |
81 | 105 | }); |
82 | 106 | } |
83 | 107 |
|
|
0 commit comments