diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index fa51284aad..f462bb01d5 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -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 diff --git a/crates/revm/README.md b/crates/revm/README.md new file mode 100644 index 0000000000..a8a11780a1 --- /dev/null +++ b/crates/revm/README.md @@ -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. diff --git a/crates/revm/benches/criterion_bytecode.rs b/crates/revm/benches/criterion_bytecode.rs new file mode 100644 index 0000000000..7fba9de92a --- /dev/null +++ b/crates/revm/benches/criterion_bytecode.rs @@ -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);