Skip to content
Open
5 changes: 5 additions & 0 deletions crates/revm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,8 @@ path = "../../examples/fork_ref_transact.rs"
name = "bench"
path = "benches/bench.rs"
harness = false

[[bench]]
name = "criterion_bytecode"
path = "benches/criterion_bytecode.rs"
harness = false
22 changes: 22 additions & 0 deletions crates/revm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# REVM benchmark

Benchmark goes in two runs.
One is for passed bytecode.
The second one is for bytecode prefixed with 00 code (STOP) - this is to determine the overhead from revm setup only.

## How to run

Install Rust and Cargo:

`curl https://sh.rustup.rs -sSf | sh`

Pass bytecode string as stdin to benchmark:

`echo "6062" | cargo bench --bench criterion_bytecode`

For more verbose output:

`echo "6062" | cargo bench --bench criterion_bytecode -- --verbose`

## Debug
For debug information set environmental variable CRITERION_DEBUG=1.
85 changes: 85 additions & 0 deletions crates/revm/benches/criterion_bytecode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use bytes::Bytes;
use criterion::{criterion_group, criterion_main, Criterion};
use revm::{
db::BenchmarkDB,
interpreter::{analysis::to_analysed, BytecodeLocked, Contract, DummyHost, Interpreter},
primitives::{LatestSpec, Bytecode, TransactTo}
};
use std::io;
use std::time::{Duration, Instant};

extern crate alloc;

pub fn criterion_benchmark(_c: &mut Criterion) {
let mut code_input = String::new();
let stdin = io::stdin();
match stdin.read_line(&mut code_input){
Ok(_n) => {}
Err(_error) => {}
}
if code_input.trim().len() == 0 {
println!("Empty bytecode on stdin.");
return
}
let code_input = code_input.trim();
let bytecode = to_analysed(Bytecode::new_raw(hex::decode(code_input).unwrap().into()));
let stop_bytecode = to_analysed(Bytecode::new_raw(hex::decode("00".to_string() + code_input).unwrap().into()));

// EVM preparation
let mut evm = revm::new();
evm.env.tx.caller = "0x1000000000000000000000000000000000000000"
.parse()
.unwrap();
evm.env.tx.transact_to = TransactTo::Call(
"0x0000000000000000000000000000000000000000"
.parse()
.unwrap(),
);
evm.env.tx.data = Bytes::from(hex::decode("").unwrap());
evm.database(BenchmarkDB::new_bytecode(Bytecode::new()));

let contract = Contract {
input: Bytes::from(hex::decode("").unwrap()),
bytecode: BytecodeLocked::try_from(bytecode).unwrap(),
..Default::default()
};
let stop_contract = Contract {
input: Bytes::from(hex::decode("").unwrap()),
bytecode: BytecodeLocked::try_from(stop_bytecode).unwrap(),
..Default::default()
};

let mut group = _c.benchmark_group("bytecode");
group.warm_up_time(Duration::from_micros(50000));
group.measurement_time(Duration::from_micros(200000));
group.bench_function("bytecode-benchmark", |b| {
b.iter_custom(|iters| {
let mut dur = Duration::from_nanos(0);
for _i in 0..iters {
let mut interpreter = Interpreter::new(Box::new(contract.clone()), u64::MAX, false);
let mut host = DummyHost::new(evm.env.clone());
let timer = Instant::now();
interpreter.run::<_, LatestSpec>(&mut host);
dur += timer.elapsed();
}
dur
})
});
group.bench_function("bytecode-benchmark-stop", |b| {
b.iter_custom(|iters| {
let mut dur = Duration::from_nanos(0);
for _i in 0..iters {
let mut interpreter = Interpreter::new(Box::new(stop_contract.clone()), u64::MAX, false);
let mut host = DummyHost::new(evm.env.clone());
let timer = Instant::now();
interpreter.run::<_, LatestSpec>(&mut host);
dur += timer.elapsed();
}
dur
})
});
group.finish();
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);