Skip to content

Commit c1aabe2

Browse files
authored
Update README.md
1 parent d68e745 commit c1aabe2

File tree

1 file changed

+145
-1
lines changed

1 file changed

+145
-1
lines changed

cosmwasm/README.md

Lines changed: 145 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,151 @@ You may want to compare how long the contract takes to run inside the Wasm VM
365365
compared to in native rust code, especially for computationally intensive code,
366366
like hashing or signature verification.
367367

368-
**TODO** add instructions
368+
Here's how to benchmark your CosmWasm contracts:
369+
370+
### Native Rust Benchmarking
371+
372+
1. Add the `criterion` crate to your `dev-dependencies` in `Cargo.toml`:
373+
```toml
374+
[dev-dependencies]
375+
criterion = "0.4"
376+
```
377+
378+
2. Create a `benches` directory in your project root and add a benchmark file (e.g., `benches/my_benchmark.rs`):
379+
```rust
380+
use criterion::{black_box, criterion_group, criterion_main, Criterion};
381+
use your_contract::contract::{execute, instantiate}; // Import your contract functions
382+
use your_contract::msg::{ExecuteMsg, InstantiateMsg};
383+
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
384+
385+
fn instantiate_benchmark(c: &mut Criterion) {
386+
let mut deps = mock_dependencies();
387+
let env = mock_env();
388+
let info = mock_info("creator", &[]);
389+
let msg = InstantiateMsg { /* your params here */ };
390+
391+
c.bench_function("instantiate", |b| {
392+
b.iter(|| instantiate(black_box(&mut deps), black_box(env.clone()), black_box(info.clone()), black_box(msg.clone())))
393+
});
394+
}
395+
396+
fn execute_benchmark(c: &mut Criterion) {
397+
// Set up contract state first by instantiating
398+
let mut deps = mock_dependencies();
399+
let env = mock_env();
400+
let info = mock_info("creator", &[]);
401+
let init_msg = InstantiateMsg { /* your params here */ };
402+
let _ = instantiate(&mut deps, env.clone(), info.clone(), init_msg).unwrap();
403+
404+
// Now benchmark execute
405+
let exec_msg = ExecuteMsg::YourAction { /* params */ };
406+
c.bench_function("execute_your_action", |b| {
407+
b.iter(|| execute(black_box(&mut deps), black_box(env.clone()), black_box(info.clone()), black_box(exec_msg.clone())))
408+
});
409+
}
410+
411+
criterion_group!(benches, instantiate_benchmark, execute_benchmark);
412+
criterion_main!(benches);
413+
```
414+
415+
3. Run the benchmarks with:
416+
```sh
417+
cargo bench
418+
```
419+
420+
### Wasm VM Benchmarking
421+
422+
To benchmark in the Wasm VM environment:
423+
424+
1. Add `cosmwasm-vm` to your `dev-dependencies`:
425+
```toml
426+
[dev-dependencies]
427+
cosmwasm-vm = { version = "1.3", features = ["stargate"] }
428+
```
429+
430+
2. Create a benchmark file in your `tests` directory:
431+
```rust
432+
#[cfg(test)]
433+
mod vm_benchmarks {
434+
use cosmwasm_std::{Addr, Coin, Empty};
435+
use cosmwasm_vm::{
436+
testing::{mock_backend, mock_env, mock_info, MockApi, MockQuerier, MockStorage},
437+
Instance, InstanceOptions, Module,
438+
};
439+
use std::time::Instant;
440+
441+
#[test]
442+
fn benchmark_wasm_execution() {
443+
// Compile contract
444+
let wasm = std::fs::read("./target/wasm32-unknown-unknown/release/your_contract.wasm")
445+
.expect("Failed to read Wasm file");
446+
447+
// Create VM instance
448+
let backend = mock_backend(&[]);
449+
let options = InstanceOptions {
450+
gas_limit: 100_000_000,
451+
print_debug: false,
452+
};
453+
let module = Module::from_code(&wasm).unwrap();
454+
let mut instance = Instance::from_module(
455+
&module,
456+
backend,
457+
options,
458+
MockStorage::default(),
459+
MockApi::default(),
460+
MockQuerier::default(),
461+
)
462+
.unwrap();
463+
464+
// Prepare instantiate message
465+
let info = mock_info("creator", &[]);
466+
let instantiate_msg = r#"{"your_param": "value"}"#;
467+
468+
// Benchmark instantiate
469+
let start = Instant::now();
470+
let _res = instance.instantiate(
471+
&mock_env("creator", &[]),
472+
&info,
473+
instantiate_msg.as_bytes(),
474+
).unwrap();
475+
let duration = start.elapsed();
476+
println!("Instantiate execution time: {:?}", duration);
477+
478+
// Prepare execute message
479+
let execute_msg = r#"{"your_action": {"param": "value"}}"#;
480+
481+
// Benchmark execute
482+
let start = Instant::now();
483+
let _res = instance.execute(
484+
&mock_env("user", &[]),
485+
&info,
486+
execute_msg.as_bytes(),
487+
).unwrap();
488+
let duration = start.elapsed();
489+
println!("Execute execution time: {:?}", duration);
490+
}
491+
}
492+
```
493+
494+
3. Build your Wasm contract:
495+
```sh
496+
RUSTFLAGS='-C link-arg=-s' cargo wasm --release
497+
```
498+
499+
4. Run the benchmark:
500+
```sh
501+
cargo test vm_benchmarks --release -- --nocapture
502+
```
503+
504+
### Comparing Results
505+
506+
When comparing the results, keep in mind:
507+
508+
1. The Wasm VM adds overhead for serialization/deserialization of data
509+
2. The VM has gas metering which adds additional overhead
510+
3. The compilation flags used for Wasm optimization can significantly affect performance
511+
512+
For a comprehensive comparison, record multiple runs for each benchmark to account for variance.
369513

370514
## Developing
371515

0 commit comments

Comments
 (0)