Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: wasm::Module benchmark #109

Merged
merged 43 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
e095499
add HermesEventPayload trait, update wasm Module
Mr-Leshiy Feb 8, 2024
4f490d1
refactor
Mr-Leshiy Feb 8, 2024
eeeb90d
refactor
Mr-Leshiy Feb 8, 2024
f4e333c
update test
Mr-Leshiy Feb 8, 2024
de56aef
update
Mr-Leshiy Feb 8, 2024
f789e29
add docs
Mr-Leshiy Feb 8, 2024
c0092a8
update
Mr-Leshiy Feb 8, 2024
855b5db
fix spelling
Mr-Leshiy Feb 8, 2024
3d06b90
update
Mr-Leshiy Feb 8, 2024
d535093
refactor Context
Mr-Leshiy Feb 8, 2024
ca49797
refactor
Mr-Leshiy Feb 8, 2024
660eb5a
update wasm::module
Mr-Leshiy Feb 8, 2024
57cab29
fix formating
Mr-Leshiy Feb 9, 2024
4e05ff3
commented out test
Mr-Leshiy Feb 9, 2024
b3a110d
move event mod under the event_queue mod
Mr-Leshiy Feb 9, 2024
cb3a602
move bindings mod to the separate file
Mr-Leshiy Feb 9, 2024
421411f
move Context and Statefull to another module
Mr-Leshiy Feb 9, 2024
aa551ed
update error handling
Mr-Leshiy Feb 9, 2024
aed5512
fix docs
Mr-Leshiy Feb 9, 2024
c14fae7
Merge branch 'main' into feat/hermes-executor
Mr-Leshiy Feb 9, 2024
5176a16
Merge branch 'main' into feat/hermes-executor
Mr-Leshiy Feb 10, 2024
35b861a
update errors
Mr-Leshiy Feb 13, 2024
673e01b
setup benchmarks
Mr-Leshiy Feb 13, 2024
58a58f8
add module_hermes_component_bench
Mr-Leshiy Feb 13, 2024
aa838af
add module_small_component_bench, module_small_component_full_pre_loa…
Mr-Leshiy Feb 13, 2024
2a7409d
Merge branch 'main' into feat/wasm-module-bench
Mr-Leshiy Feb 13, 2024
8e533e9
add documentation
Mr-Leshiy Feb 13, 2024
9eb2ad1
update earthfile
Mr-Leshiy Feb 13, 2024
170614e
wip
Mr-Leshiy Feb 13, 2024
356bc73
Merge branch 'main' into feat/wasm-module-bench
Mr-Leshiy Feb 15, 2024
98c7865
fix and update Readme
Mr-Leshiy Feb 15, 2024
c52e981
Merge branch 'main' into feat/wasm-module-bench
Mr-Leshiy Feb 21, 2024
a9b76f1
Use already prepared C wasm module
Mr-Leshiy Feb 21, 2024
fc0d228
fix README.md
Mr-Leshiy Feb 21, 2024
f492cc2
fix spelling
Mr-Leshiy Feb 21, 2024
2b71107
wip
Mr-Leshiy Feb 26, 2024
3d5325b
wip
Mr-Leshiy Feb 26, 2024
6ed44f1
Merge branch 'main' into feat/wasm-module-bench
Mr-Leshiy Feb 26, 2024
79562c1
fix deny.toml
Mr-Leshiy Feb 26, 2024
a40e7cd
Merge branch 'main' into feat/wasm-module-bench
Mr-Leshiy Feb 26, 2024
cef0e1c
bump rust builder
Mr-Leshiy Feb 27, 2024
12176cd
fix deny.toml
Mr-Leshiy Feb 27, 2024
52bad52
fix
Mr-Leshiy Feb 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@
"ignorePaths": [
".config/dictionaries/**",
"*.svg",
"*.wasm",
"tmp/**",
"cspell.json",
".git/**",
Expand Down
1 change: 1 addition & 0 deletions hermes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ anyhow = "1.0.71"
blake2b_simd = "1.0.2"
hex-literal = "0.4.1"
thiserror = "1.0.56"
criterion = "0.5.1"
time = "0.3.34"
8 changes: 6 additions & 2 deletions hermes/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ VERSION 0.7

# Set up our target toolchains, and copy our files.
builder:
DO github.com/input-output-hk/catalyst-ci/earthly/rust:v2.9.0+SETUP
DO github.com/input-output-hk/catalyst-ci/earthly/rust:v2.9.3+SETUP

COPY --dir .cargo .config crates bin .
COPY Cargo.toml .
COPY clippy.toml deny.toml rustfmt.toml .

RUN mkdir /wasm
COPY --dir ../wasm+wasi-src/wasi /wasm/wasi
# Compiled WASM component for benchmarks
COPY ../wasm/c+build/component.wasm /wasm/c/bench_component.wasm

# Expands `wasmtime::bindgen!` macro into the `bindings.rs` file
bindings-expand:
Expand Down Expand Up @@ -43,11 +45,13 @@ all-hosts-check:
build:
FROM +builder

RUN /scripts/std_build.py --libs="cardano-chain-follower" \
RUN /scripts/std_build.py --bench_flags="--features bench" \
--libs="cardano-chain-follower" \
--bins="hermes/hermes"

SAVE ARTIFACT target/$TARGETARCH/doc doc
SAVE ARTIFACT target/$TARGETARCH/release/hermes hermes
SAVE ARTIFACT target/criterion

# Test which runs check with all supported host tooling. Needs qemu or rosetta to run.
# Only used to validate tooling is working across host toolsets.
Expand Down
14 changes: 14 additions & 0 deletions hermes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,17 @@ This workaround has effectively bypassed the mentioned problems until a permanen
```shell
CARGO_FEATURE_STD=1 cargo b
```

## Running benchmarks

Before running benchmarks need to compile a simple WASM module:

```shell
earthly ./wasm/c+save-local
```

And then you can run benchmarks:

```shell
cargo bench --features bench
```
9 changes: 9 additions & 0 deletions hermes/bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,23 @@ edition.workspace = true
license.workspace = true
repository.workspace = true

[features]
bench = ["dep:criterion"]

[lints]
workspace = true

[[bench]]
name = "module"
harness = false
required-features = ["bench"]

[dependencies]
wasmtime = { workspace = true, features = ["component-model"] }
rusty_ulid = { workspace = true }
anyhow = { workspace = true }
blake2b_simd = { workspace = true }
hex-literal = { workspace = true }
thiserror = { workspace = true }
criterion = { workspace = true, optional = true }
time = { workspace = true }
24 changes: 24 additions & 0 deletions hermes/bin/benches/module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//! `wasm::Module` benchmark
#![allow(missing_docs, clippy::missing_docs_in_private_items)]

use criterion::{criterion_group, criterion_main, Criterion};

fn module_benches(c: &mut Criterion) {
let mut group = c.benchmark_group("WASM module execution");
group.bench_function("module_hermes_component_bench", |b| {
hermes::module_hermes_component_bench(b)
});

group.bench_function("module_small_component_bench", |b| {
hermes::module_small_component_bench(b)
});

group.bench_function("module_small_component_full_pre_load_bench", |b| {
hermes::module_small_component_full_pre_load_bench(b)
});
group.finish();
}

criterion_group!(benches, module_benches);

criterion_main!(benches);
6 changes: 6 additions & 0 deletions hermes/bin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ mod event_queue;
mod runtime_extensions;
mod state;
mod wasm;

#[cfg(feature = "bench")]
pub use wasm::module::bench::{
module_hermes_component_bench, module_small_component_bench,
module_small_component_full_pre_load_bench,
};
6 changes: 6 additions & 0 deletions hermes/bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ mod runtime_extensions;
mod state;
mod wasm;

#[cfg(feature = "bench")]
pub use wasm::module::bench::{
module_hermes_component_bench, module_small_component_bench,
module_small_component_full_pre_load_bench,
};

fn main() {
println!("Hello, world!");
}
106 changes: 104 additions & 2 deletions hermes/bin/src/wasm/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ impl Module {
#[allow(dead_code)]
pub(crate) fn new(app_name: String, module_bytes: &[u8]) -> anyhow::Result<Self> {
let engine = Engine::new()?;
let module = WasmModule::new(&engine, module_bytes)
let wasm_module = WasmModule::new(&engine, module_bytes)
.map_err(|e| BadWASMModuleError(e.to_string()))?;

let mut linker = WasmLinker::new(&engine);
bindings::Hermes::add_to_linker(&mut linker, |state: &mut HermesState| state)
.map_err(|e| BadWASMModuleError(e.to_string()))?;
let pre_instance = linker
.instantiate_pre(&module)
.instantiate_pre(&wasm_module)
.map_err(|e| BadWASMModuleError(e.to_string()))?;

Ok(Self {
Expand Down Expand Up @@ -107,6 +107,108 @@ impl Module {
}
}

#[cfg(feature = "bench")]
pub mod bench {
use super::*;

/// Benchmark for executing the `init` event of the Hermes dummy component.
/// It aims to measure the overhead of the WASM module and WASM state initialization
/// process.
pub fn module_hermes_component_bench(b: &mut criterion::Bencher) {
struct Event;
impl HermesEventPayload for Event {
fn event_name(&self) -> &str {
"init"
}

fn execute(&self, instance: &mut ModuleInstance) -> anyhow::Result<()> {
instance
.instance
.hermes_init_event()
.call_init(&mut instance.store)?;
Ok(())
}
}

let mut module = Module::new(
"app".to_string(),
include_bytes!("../../../../wasm/c/bench_component.wasm"),
)
.unwrap();

b.iter(|| {
module.execute_event(&Event).unwrap();
});
}

/// Benchmark for executing the `foo` WASM function of the tiny component.
/// The general flow of how WASM module is instantiated and executed is the same as in
/// the previous one `module_hermes_component_bench`.
/// It aims to compare how the size of the component affects on the execution time.
pub fn module_small_component_bench(b: &mut criterion::Bencher) {
let wat = r#"
(component
(core module $Module
(export "foo" (func $foo))
(func $foo (result i32)
i32.const 1
)
)
(core instance $module (instantiate (module $Module)))
(func $foo (result s32) (canon lift (core func $module "foo")))
(export "foo" (func $foo))
)"#;

let engine = Engine::new().unwrap();
bkioshn marked this conversation as resolved.
Show resolved Hide resolved
let module = WasmModule::new(&engine, wat.as_bytes()).unwrap();
let linker = WasmLinker::new(&engine);
let pre_instance = linker.instantiate_pre(&module).unwrap();

b.iter(|| {
let mut store = WasmStore::new(&engine, ());
let instance = pre_instance.instantiate(&mut store).unwrap();
let func = instance
.get_typed_func::<(), (i32,)>(&mut store, "foo")
.unwrap();
let (res,) = func.call(&mut store, ()).unwrap();
assert_eq!(res, 1);
});
}

/// Benchmark for executing the `foo` WASM function of the tiny component.
/// BUT with the changed execution flow. Here the WASM module and WASM state is
/// instantiated ONCE during the whole execution process.
pub fn module_small_component_full_pre_load_bench(b: &mut criterion::Bencher) {
let wat = r#"
(component
(core module $Module
(export "foo" (func $foo))
(func $foo (result i32)
i32.const 1
)
)
(core instance $module (instantiate (module $Module)))
(func $foo (result s32) (canon lift (core func $module "foo")))
(export "foo" (func $foo))
)"#;

let engine = Engine::new().unwrap();
let module = WasmModule::new(&engine, wat.as_bytes()).unwrap();
let linker = WasmLinker::new(&engine);
let mut store = WasmStore::new(&engine, ());
let instance = linker.instantiate(&mut store, &module).unwrap();
let func = instance
.get_typed_func::<(), (i32,)>(&mut store, "foo")
.unwrap();

b.iter(|| {
let (res,) = func.call(&mut store, ()).unwrap();
assert_eq!(res, 1);
func.post_return(&mut store).unwrap();
});
}
}

#[cfg(test)]
mod tests {
// use super::*;
Expand Down
4 changes: 1 addition & 3 deletions hermes/deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,7 @@ unknown-git = "deny"
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
# List of URLs for allowed Git repositories
allow-git = [
# Remove this once upstream changes are merged.
# issue: https://github.com/input-output-hk/hermes/issues/63
"https://github.com/input-output-hk/catalyst-pallas"
"https://github.com/input-output-hk/hermes.git"
]

[sources.allow-org]
Expand Down
7 changes: 7 additions & 0 deletions wasm/event-stubs/Earthfile → wasm/c/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,10 @@ build:
RUN /scripts/std_build.py --wit_path="wit" --c_files="my-component.c" --out="component.wasm"

SAVE ARTIFACT component.wasm

# Build and locally save an output artifact
save-local:
FROM scratch

COPY +build/component.wasm .
SAVE ARTIFACT component.wasm AS LOCAL bench_component.wasm
File renamed without changes.
2 changes: 1 addition & 1 deletion wasm/wasi-hermes-component-adapter/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ VERSION 0.7

# Set up our target toolchains, and copy source files.
builder:
DO github.com/input-output-hk/catalyst-ci/earthly/rust:v2.9.0+SETUP
DO github.com/input-output-hk/catalyst-ci/earthly/rust:v2.9.3+SETUP

COPY --dir .cargo .config src byte-array-literals .
COPY ..+wasi-src/wasi ../wasi
Expand Down
4 changes: 1 addition & 3 deletions wasm/wasi-hermes-component-adapter/deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,7 @@ unknown-git = "deny"
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
# List of URLs for allowed Git repositories
allow-git = [
# Remove this once upstream changes are merged.
# issue: https://github.com/input-output-hk/hermes/issues/63
"https://github.com/input-output-hk/catalyst-pallas"
"https://github.com/input-output-hk/hermes.git"
]

[sources.allow-org]
Expand Down
Loading