Skip to content

Commit 6f38322

Browse files
authored
feat: Add criterion to revme bench command (#2295)
* temp code preview * add criterion to benchmarks * added args to fn run() calls in bins/revme/ * modifed the code inside the benchmark tests * left only .replay function inside bench_functions and added minor revisions to the rest of the code * edited comment annotation in burntpix.rs file * added comments and set different default value for warm_up_time
1 parent efe528e commit 6f38322

File tree

7 files changed

+104
-98
lines changed

7 files changed

+104
-98
lines changed

bins/revme/Cargo.toml

+1-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ context-interface.workspace = true
2727
handler.workspace = true
2828
inspector = { workspace = true, features = ["std", "serde-json"] }
2929
statetest-types.workspace = true
30+
criterion.workspace = true
3031

3132
# alloy
3233
alloy-rlp = { workspace = true, features = ["arrayvec", "derive"] }
@@ -45,9 +46,6 @@ triehash.workspace = true
4546
walkdir.workspace = true
4647
k256 = { workspace = true, features = ["ecdsa"] }
4748

48-
[dev-dependencies]
49-
criterion.workspace = true
50-
5149
[[bench]]
5250
name = "evm"
5351
harness = false

bins/revme/benches/evm.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
11
use criterion::{criterion_group, criterion_main, Criterion};
2-
use revme::cmd::{
3-
bench::{self, BenchName},
4-
MainCmd,
5-
};
2+
use revme::cmd::bench;
63

74
fn evm(c: &mut Criterion) {
8-
// call analysis to init static data.
9-
revme::cmd::bench::analysis::run();
10-
11-
for &bench_name in BenchName::ALL {
12-
let cmd = MainCmd::Bench(bench::Cmd { name: bench_name });
13-
c.bench_function(bench_name.as_str(), |b| {
14-
b.iter(|| cmd.run().unwrap());
15-
});
16-
}
5+
bench::analysis::run(c);
6+
bench::burntpix::run(c);
7+
bench::snailtracer::run(c);
8+
bench::transfer::run(c);
179
}
18-
1910
criterion_group!(benches, evm);
2011
criterion_main!(benches);

bins/revme/src/cmd/bench.rs

+29-4
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,41 @@ impl BenchName {
3636
pub struct Cmd {
3737
#[arg(value_enum)]
3838
pub name: BenchName,
39+
/// Warmup represents warm up time for benchmarks ran
40+
#[arg(short = 'w', long)]
41+
pub warmup: Option<f64>,
42+
/// Samples represents default measurement time for benchmarks ran
43+
#[arg(short = 'm', long)]
44+
pub time: Option<f64>,
45+
/// Samples represents size of the sample for benchmarks ran
46+
#[arg(short = 's', long)]
47+
pub samples: Option<usize>,
3948
}
4049

4150
impl Cmd {
4251
/// Runs bench command.
4352
pub fn run(&self) {
53+
let mut criterion = criterion::Criterion::default()
54+
.warm_up_time(std::time::Duration::from_secs_f64(
55+
self.warmup.unwrap_or(0.5),
56+
))
57+
// Measurement_time of 0.1 will get 500+ iterations for analysis and transfer and will be extended if needed in order to test the given sample size (minimum sample size is 10 per criterion documentation) as is the case with burntpix and snailtracer benchmark tests
58+
.measurement_time(std::time::Duration::from_secs_f64(self.time.unwrap_or(0.1)))
59+
.sample_size(self.samples.unwrap_or(10));
60+
4461
match self.name {
45-
BenchName::Analysis => analysis::run(),
46-
BenchName::Burntpix => burntpix::run(),
47-
BenchName::Snailtracer => snailtracer::run(),
48-
BenchName::Transfer => transfer::run(),
62+
BenchName::Analysis => {
63+
analysis::run(&mut criterion);
64+
}
65+
BenchName::Burntpix => {
66+
burntpix::run(&mut criterion);
67+
}
68+
BenchName::Snailtracer => {
69+
snailtracer::run(&mut criterion);
70+
}
71+
BenchName::Transfer => {
72+
transfer::run(&mut criterion);
73+
}
4974
}
5075
}
5176
}

bins/revme/src/cmd/bench/analysis.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use std::time::Instant;
2-
1+
use criterion::Criterion;
32
use database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET};
43
use revm::{
54
bytecode::Bytecode,
@@ -9,9 +8,8 @@ use revm::{
98

109
const BYTES: &str = include_str!("analysis.hex");
1110

12-
pub fn run() {
11+
pub fn run(criterion: &mut Criterion) {
1312
let bytecode = Bytecode::new_raw(Bytes::from(hex::decode(BYTES).unwrap()));
14-
1513
// BenchmarkDB is dummy state that implements Database trait.
1614
let context = Context::mainnet()
1715
.with_db(BenchmarkDB::new_bytecode(bytecode))
@@ -21,14 +19,10 @@ pub fn run() {
2119
tx.kind = TxKind::Call(BENCH_TARGET);
2220
tx.data = bytes!("8035F0CE");
2321
});
24-
2522
let mut evm = context.build_mainnet();
26-
27-
let time = Instant::now();
28-
let _ = evm.replay();
29-
println!("First init: {:?}", time.elapsed());
30-
31-
let time = Instant::now();
32-
let _ = evm.replay();
33-
println!("Run: {:?}", time.elapsed());
23+
criterion.bench_function("analysis", |b| {
24+
b.iter(|| {
25+
let _ = evm.replay();
26+
});
27+
});
3428
}

bins/revme/src/cmd/bench/burntpix.rs

+46-41
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod static_data;
22

3+
use criterion::Criterion;
34
use static_data::{
45
BURNTPIX_ADDRESS_ONE, BURNTPIX_ADDRESS_THREE, BURNTPIX_ADDRESS_TWO, BURNTPIX_BYTECODE_FOUR,
56
BURNTPIX_BYTECODE_ONE, BURNTPIX_BYTECODE_THREE, BURNTPIX_BYTECODE_TWO, BURNTPIX_MAIN_ADDRESS,
@@ -9,17 +10,15 @@ use static_data::{
910
use alloy_sol_types::{sol, SolCall};
1011
use database::{CacheDB, BENCH_CALLER};
1112
use revm::{
12-
context_interface::result::{ExecutionResult, Output},
1313
database_interface::EmptyDB,
1414
primitives::{hex, keccak256, Address, Bytes, TxKind, B256, U256},
1515
state::{AccountInfo, Bytecode},
1616
Context, ExecuteEvm, MainBuilder, MainContext,
1717
};
1818

19-
use std::fs::File;
20-
use std::{error::Error, time::Instant};
19+
use std::error::Error;
2120

22-
use std::{io::Write, str::FromStr};
21+
use std::str::FromStr;
2322

2423
sol! {
2524
#[derive(Debug, PartialEq, Eq)]
@@ -28,7 +27,7 @@ sol! {
2827
}
2928
}
3029

31-
pub fn run() {
30+
pub fn run(criterion: &mut Criterion) {
3231
let (seed, iterations) = try_init_env_vars().expect("Failed to parse env vars");
3332

3433
let run_call_data = IBURNTPIX::runCall { seed, iterations }.abi_encode();
@@ -45,46 +44,52 @@ pub fn run() {
4544
})
4645
.build_mainnet();
4746

48-
let started = Instant::now();
49-
let tx_result = evm.replay().unwrap().result;
50-
let return_data = match tx_result {
51-
ExecutionResult::Success {
52-
output, gas_used, ..
53-
} => {
54-
println!("Gas used: {:?}", gas_used);
55-
println!("Time elapsed: {:?}", started.elapsed());
56-
match output {
57-
Output::Call(value) => value,
58-
_ => unreachable!("Unexpected output type"),
59-
}
60-
}
61-
_ => unreachable!("Execution failed: {:?}", tx_result),
62-
};
63-
64-
// Remove returndata offset and length from output
65-
let returndata_offset = 64;
66-
let data = &return_data[returndata_offset..];
67-
68-
// Remove trailing zeros
69-
let trimmed_data = data
70-
.split_at(data.len() - data.iter().rev().filter(|&x| *x == 0).count())
71-
.0;
72-
let file_name = format!("{}_{}", seed, iterations);
73-
74-
svg(file_name, trimmed_data).expect("Failed to store svg");
47+
criterion.bench_function("burntpix", |b| {
48+
b.iter(|| {
49+
let _ = evm.replay();
50+
})
51+
});
52+
53+
// Collects the data and uses it to generate the svg after running the benchmark
54+
// let return_data = match tx_result {
55+
// ExecutionResult::Success {
56+
// output, gas_used, ..
57+
// } => {
58+
// println!("Gas used: {:?}", gas_used);
59+
// match output {
60+
// Output::Call(value) => value,
61+
// _ => unreachable!("Unexpected output type"),
62+
// }
63+
// }
64+
// _ => unreachable!("Execution failed: {:?}", tx_result),
65+
// };
66+
67+
// // Remove returndata offset and length from output
68+
// let returndata_offset = 64;
69+
// let data = &return_data[returndata_offset..];
70+
71+
// // Remove trailing zeros
72+
// let trimmed_data = data
73+
// .split_at(data.len() - data.iter().rev().filter(|&x| *x == 0).count())
74+
// .0;
75+
// let file_name = format!("{}_{}", seed, iterations);
76+
77+
// svg(file_name, trimmed_data).expect("Failed to store svg");
78+
// });
7579
}
7680

77-
fn svg(filename: String, svg_data: &[u8]) -> Result<(), Box<dyn Error>> {
78-
let current_dir = std::env::current_dir()?;
79-
let svg_dir = current_dir.join("burntpix").join("svgs");
80-
std::fs::create_dir_all(&svg_dir)?;
81+
// Actually generates the svg
82+
// fn svg(filename: String, svg_data: &[u8]) -> Result<(), Box<dyn Error>> {
83+
// let current_dir = std::env::current_dir()?;
84+
// let svg_dir = current_dir.join("burntpix").join("svgs");
85+
// std::fs::create_dir_all(&svg_dir)?;
8186

82-
let file_path = svg_dir.join(format!("{}.svg", filename));
83-
let mut file = File::create(file_path)?;
84-
file.write_all(svg_data)?;
87+
// let file_path = svg_dir.join(format!("{}.svg", filename));
88+
// let mut file = File::create(file_path)?;
89+
// file.write_all(svg_data)?;
8590

86-
Ok(())
87-
}
91+
// Ok(())
92+
// }
8893

8994
const DEFAULT_SEED: &str = "0";
9095
const DEFAULT_ITERATIONS: &str = "0x7A120";
+9-11
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
use criterion::Criterion;
12
use database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET};
23
use revm::{
34
bytecode::Bytecode,
45
primitives::{bytes, hex, Bytes, TxKind},
56
Context, ExecuteEvm, MainBuilder, MainContext,
67
};
78

8-
pub fn simple_example(bytecode: Bytecode) {
9+
pub fn run(criterion: &mut Criterion) {
10+
let bytecode = Bytecode::new_raw(Bytes::from(hex::decode(BYTES).unwrap()));
11+
912
let mut evm = Context::mainnet()
1013
.with_db(BenchmarkDB::new_bytecode(bytecode.clone()))
1114
.modify_tx_chained(|tx| {
@@ -16,16 +19,11 @@ pub fn simple_example(bytecode: Bytecode) {
1619
tx.gas_limit = 1_000_000_000;
1720
})
1821
.build_mainnet();
19-
let _ = evm.replay().unwrap();
20-
}
21-
22-
pub fn run() {
23-
println!("Running snailtracer example!");
24-
let bytecode = Bytecode::new_raw(Bytes::from(hex::decode(BYTES).unwrap()));
25-
let start = std::time::Instant::now();
26-
simple_example(bytecode);
27-
let elapsed = start.elapsed();
28-
println!("elapsed: {:?}", elapsed);
22+
criterion.bench_function("snailtracer", |b| {
23+
b.iter(|| {
24+
let _ = evm.replay().unwrap();
25+
})
26+
});
2927
}
3028

3129
const BYTES: &str = include_str!("snailtracer.hex");

bins/revme/src/cmd/bench/transfer.rs

+7-12
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1+
use criterion::Criterion;
12
use database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET};
23
use revm::{
34
bytecode::Bytecode,
45
primitives::{TxKind, U256},
56
Context, ExecuteEvm, MainBuilder, MainContext,
67
};
7-
use std::time::Instant;
88

9-
pub fn run() {
10-
let time = Instant::now();
9+
pub fn run(criterion: &mut Criterion) {
1110
let mut evm = Context::mainnet()
1211
.with_db(BenchmarkDB::new_bytecode(Bytecode::new()))
1312
.modify_tx_chained(|tx| {
@@ -17,13 +16,9 @@ pub fn run() {
1716
tx.value = U256::from(10);
1817
})
1918
.build_mainnet();
20-
println!("Init: {:?}", time.elapsed());
21-
22-
let time = Instant::now();
23-
let _ = evm.replay();
24-
println!("First run: {:?}", time.elapsed());
25-
26-
let time = Instant::now();
27-
let _ = evm.replay();
28-
println!("Second run: {:?}", time.elapsed());
19+
criterion.bench_function("transfer", |b| {
20+
b.iter(|| {
21+
let _ = evm.replay();
22+
})
23+
});
2924
}

0 commit comments

Comments
 (0)