Skip to content

Commit

Permalink
add benchmark tests
Browse files Browse the repository at this point in the history
  • Loading branch information
cassc committed Jul 17, 2024
1 parent 3677a54 commit 0ce9b80
Show file tree
Hide file tree
Showing 8 changed files with 354 additions and 3 deletions.
19 changes: 19 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,22 @@ criterion = {version="0.3.6", features=["html_reports"] }
[features]
default = []
redis=["dep:redis"]

[[bench]]
name = "general"
harness = false

[[bench]]
name = "deploy"
harness = false

[[bench]]
name = "infinite_loop"
harness = false

[[bench]]
name = "function"
harness = false

[profile.bench]
debug = true
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ build:
test:
cargo nextest run --no-fail-fast --success-output=never
maturin develop --release
pytest -s --show-capture all
pytest -s
bench:
cargo bench
clean:
Expand Down
44 changes: 44 additions & 0 deletions benches/complex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use std::time::Duration;

use criterion::{criterion_group, criterion_main, Criterion};
use revm::primitives::Address;
use tinyevm::{fn_sig_to_prefix, UZERO};

const OWNER: Address = Address::repeat_byte(0x01);
const DEPLOY_TO_ADDRESS: Address = Address::repeat_byte(0x02);

#[allow(unused)]
fn bench_call_complex_function(c: &mut Criterion) {
c.bench_function("call_complex_function", |b| {
let source = include_str!("../tests/contracts/complex_contract.hex");
let bytecode = hex::decode(source).unwrap();
let mut exe = tinyevm::TinyEVM::default();
let owner = OWNER;
let deploy_to_address = Some(DEPLOY_TO_ADDRESS);

let resp = {
exe.deploy_helper(owner, bytecode, UZERO, None, deploy_to_address)
.unwrap()
};

assert!(resp.success, "Contract deploy should succeed.");
let address = Address::from_slice(&resp.data);

let fn_sig = "complexFunction()";
b.iter(|| {
let data = hex::decode(fn_sig_to_prefix(fn_sig)).unwrap();

let r = exe.contract_call_helper(address, owner, data, UZERO, None);
// assert!(r.success); // this function can revert sometimes
assert!(r.gas_usage > 0);
})
});
}

criterion_group!(
name = complex;
config = Criterion::default().measurement_time(Duration::from_secs(10));
targets = bench_call_complex_function,
);

criterion_main!(complex);
62 changes: 62 additions & 0 deletions benches/deploy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use criterion::{criterion_group, criterion_main, Criterion};
use primitive_types::H256;
use revm::primitives::Address;
use ruint::aliases::U256;
use tinyevm::{TinyEVM, UZERO};

const OWNER: Address = Address::repeat_byte(0x01);
const DEPLOY_TO_ADDRESS: Address = Address::repeat_byte(0x02);

// Reusing can be slower because there are more data inside the instrumentation log
fn bench_contract_deterministic_deploy(c: &mut Criterion) {
c.bench_function("deploy_contract_deterministic", |b| {
let source = include_str!("../tests/contracts/calls_trace.hex");
let source = hex::decode(source).unwrap();
let mut exe = TinyEVM::default();

b.iter(|| {
{
exe.deploy_helper(OWNER, source.clone(), UZERO, None, Some(DEPLOY_TO_ADDRESS))
.unwrap();
};
})
});
}

fn bench_contract_deploy_on_different_executors(c: &mut Criterion) {
c.bench_function("deploy_contract_deploy_on_different_executors", |b| {
let source = include_str!("../tests/contracts/calls_trace.hex");
let source = hex::decode(source).unwrap();

b.iter(|| {
let mut exe = TinyEVM::default();
{
exe.deploy_helper(
OWNER,
source.clone(),
U256::from(0),
None,
Some(DEPLOY_TO_ADDRESS),
)
.unwrap();
};
})
});
}

#[allow(unused)]
fn bench_random_h256(c: &mut Criterion) {
c.bench_function("call H256 random", |b| {
b.iter(|| {
let _ = H256::random();
})
});
}

criterion_group!(
name = deploy;
config = Criterion::default();
targets = bench_random_h256, bench_contract_deterministic_deploy, bench_contract_deploy_on_different_executors
);

criterion_main!(deploy);
82 changes: 82 additions & 0 deletions benches/function.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use std::{iter::repeat_with, time::Duration};

use criterion::{criterion_group, criterion_main, Criterion};
use primitive_types::H256;
use revm::primitives::Address;
use tinyevm::{fn_sig_to_prefix, TinyEVM, UZERO};

const OWNER: Address = Address::repeat_byte(0x01);
const DEPLOY_TO_ADDRESS: Address = Address::repeat_byte(0x02);

#[allow(unused)]
fn bench_call_function_returning_large_string(c: &mut Criterion) {
c.bench_function("call_function_returning_large_string", |b| {
let source = include_str!("../tests/contracts/VeLogo.hex");
let bytecode = hex::decode(source).unwrap();
let mut exe = TinyEVM::default();

let resp = {
exe.deploy_helper(OWNER, bytecode, UZERO, None, Some(DEPLOY_TO_ADDRESS))
.unwrap()
};

assert!(resp.success, "Contract deploy should succeed.");
let address = Address::from_slice(&resp.data);

let fn_sig = "tokenURI(uint256,uint256,uint256,uint256)";
b.iter(|| {
let fn_args_hex: String = repeat_with(H256::random).take(4).map(hex::encode).collect();

let add_hex = format!("{}{}", fn_sig_to_prefix(fn_sig), fn_args_hex);

let data = hex::decode(add_hex).unwrap();

let r = exe.contract_call_helper(address, OWNER, data, UZERO, None);
assert!(r.success);
})
});
}

#[allow(unused)]
// TODO this repeats most part of the previous test function, refactor
fn bench_call_function_returning_large_string_no_instrumentation(c: &mut Criterion) {
c.bench_function(
"call_function_returning_large_string_no_instrumetation",
|b| {
let source = include_str!("../tests/contracts/VeLogo.hex");
let bytecode = hex::decode(source).unwrap();
let mut exe = TinyEVM::default();
exe.instrument_config_mut().enabled = false;

let resp = {
exe.deploy_helper(OWNER, bytecode, UZERO, None, Some(DEPLOY_TO_ADDRESS))
.unwrap()
};

assert!(resp.success, "Contract deploy should succeed.");
let address = Address::from_slice(&resp.data);

let fn_sig = "tokenURI(uint256,uint256,uint256,uint256)";
b.iter(|| {
let fn_args_hex: String =
repeat_with(H256::random).take(4).map(hex::encode).collect();

let add_hex = format!("{}{}", fn_sig_to_prefix(fn_sig), fn_args_hex);

let data = hex::decode(add_hex).unwrap();

let r = exe.contract_call_helper(address, OWNER, data, UZERO, None);
assert!(r.success);
})
},
);
}

criterion_group!(
name = evm_benches;
config = Criterion::default().measurement_time(Duration::from_secs(10));
targets = bench_call_function_returning_large_string,
bench_call_function_returning_large_string_no_instrumentation,
);

criterion_main!(evm_benches);
69 changes: 69 additions & 0 deletions benches/general.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use criterion::{criterion_group, criterion_main, Criterion};
use revm::primitives::Address;
use tinyevm::{fn_sig_to_prefix, TinyEVM, UZERO};

const OWNER: Address = Address::repeat_byte(0x01);
const DEPLOY_TO_ADDRESS: Address = Address::repeat_byte(0x02);

#[allow(unused)]
fn bench_call_tracing_with_shared_executor(c: &mut Criterion) {
c.bench_function("call_tracing_with_shared_executor", |b| {
let source = include_str!("../tests/contracts/calls_trace.hex");
let bytecode = hex::decode(source).unwrap();
let fn_sig = "test_call_success_success_failed()";
let fn_args_hex = "";
let add_hex = format!("{}{}", fn_sig_to_prefix(fn_sig), fn_args_hex);

let data = hex::decode(add_hex).unwrap();
let mut exe = TinyEVM::default();

let resp = {
exe.deploy_helper(OWNER, bytecode, UZERO, None, Some(DEPLOY_TO_ADDRESS))
.unwrap()
};

assert!(resp.success, "Contract deploy should succeed.");
let address = Address::from_slice(&resp.data);

b.iter(|| {
let _ = exe.contract_call_helper(address, OWNER, data.clone(), UZERO, None);
})
});
}

#[allow(unused)]
fn bench_call_tracing_with_different_executor(c: &mut Criterion) {
c.bench_function("call_tracing_with_different_executor", |b| {
let source = include_str!("../tests/contracts/calls_trace.hex");
let bytecode = hex::decode(source).unwrap();
let fn_sig = "test_call_success_success_failed()";
let fn_args_hex = "";
let add_hex = format!("{}{}", fn_sig_to_prefix(fn_sig), fn_args_hex);

let data = hex::decode(add_hex).unwrap();
b.iter(|| {
let mut exe = TinyEVM::default();
let resp = exe
.deploy_helper(
OWNER,
bytecode.clone(),
UZERO,
None,
Some(DEPLOY_TO_ADDRESS),
)
.unwrap();

let address = Address::from_slice(&resp.data);

let _ = exe.contract_call_helper(address, OWNER, data.clone(), UZERO, None);
})
});
}

criterion_group!(
name = evm_benches;
config = Criterion::default();
targets = bench_call_tracing_with_shared_executor, bench_call_tracing_with_different_executor
);

criterion_main!(evm_benches);
67 changes: 67 additions & 0 deletions benches/infinite_loop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use criterion::{criterion_group, criterion_main, Criterion};
use primitive_types::{H160, U256};
use revm::primitives::Address;
use tinyevm::{fn_sig_to_prefix, TinyEVM, UZERO};

const OWNER: Address = Address::repeat_byte(0x01);
const DEPLOY_TO_ADDRESS: Address = Address::repeat_byte(0x02);

// ~100ms per loop
fn bench_infinite_loop_math(c: &mut Criterion) {
c.bench_function("infinite_loop_with_simple_math", |b| {
let source = include_str!("../tests/contracts/infinite_loop_Test2.hex");
let bytecode = hex::decode(source).unwrap();
let fn_sig = "test1(int256)";
let fn_args_hex = format!("{:0>64x}", U256::from(0));
let add_hex = format!("{}{}", fn_sig_to_prefix(fn_sig), fn_args_hex);

let data = hex::decode(add_hex).unwrap();
let mut exe = TinyEVM::default();

let resp = {
exe.deploy_helper(OWNER, bytecode, UZERO, None, Some(DEPLOY_TO_ADDRESS))
.unwrap()
};

assert!(resp.success, "Contract deploy should succeed.");
let address = Address::from_slice(&resp.data);

b.iter(|| {
let _ = exe.contract_call_helper(address, OWNER, data.clone(), UZERO, None);
})
});
}

// <300ms per loop
fn bench_infinite_loop_adderss_call(c: &mut Criterion) {
c.bench_function("infinite_loop_with_address_call", |b| {
let source = include_str!("../tests/contracts/infinite_loop_Test.hex");
let bytecode = hex::decode(source).unwrap();
let fn_sig = "test1(int256)";
let fn_args_hex = format!("{:0>64x}", U256::from(0));
let add_hex = format!("{}{}", fn_sig_to_prefix(fn_sig), fn_args_hex);

let data = hex::decode(add_hex).unwrap();
let mut exe = TinyEVM::default();

let resp = {
exe.deploy_helper(OWNER, bytecode, UZERO, None, Some(DEPLOY_TO_ADDRESS))
.unwrap()
};

assert!(resp.success, "Contract deploy should succeed.");
let address = Address::from_slice(&resp.data);

b.iter(|| {
let _ = exe.contract_call_helper(address, OWNER, data.clone(), UZERO, None);
})
});
}

criterion_group!(
name = infinite_loop;
config = Criterion::default();
targets = bench_infinite_loop_math, bench_infinite_loop_adderss_call
);

criterion_main!(infinite_loop);
12 changes: 10 additions & 2 deletions tests/revm_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,13 +381,21 @@ fn test_deterministic_deploy() {
.deploy_helper(*OWNER, contract_deploy_bin.clone(), UZERO, None, None)
.unwrap();

assert!(c1.success, "Deploy use salt 1 should succeed: {:?}", &c1);
assert!(
c1.success,
"Deploy by initial nonce should succeed: {:?}",
&c1
);

let c2 = vm
.deploy_helper(*OWNER, contract_deploy_bin, UZERO, None, None)
.unwrap();

assert!(c2.success, "Deploy use salt 2 should succeed: {:?}", &c2);
assert!(
c2.success,
"Deploy by auto updated nonce should succeed: {:?}",
&c2
);

assert_ne!(c1.data, c2.data, "Address of c1 and c2 should not equal");
}
Expand Down

0 comments on commit 0ce9b80

Please sign in to comment.