Skip to content

Commit 001cb77

Browse files
committed
Add c Component benchmark
Signed-off-by: James Sturtevant <[email protected]>
1 parent b60a313 commit 001cb77

File tree

12 files changed

+234
-93
lines changed

12 files changed

+234
-93
lines changed

.devcontainer/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,5 @@ RUN rustup default ${RUST_TOOLCHAIN} \
3535
&& cargo install --locked wasm-tools \
3636
&& cargo install wkg \
3737
&& cargo install wac-cli \
38-
&& cargo install cargo-component --locked
38+
&& cargo install cargo-component --locked \
39+
&& cargo install wit-bindgen-cli --locked

.github/workflows/dep_build_wasm_examples.yml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,14 @@ jobs:
7878
cache-to: ${{ env.CACHE_TO }}
7979
- name: Build Modules
8080
run: |
81-
for FILENAME in $(find . -name '*.c')
82-
do
83-
echo Building ${FILENAME}
84-
docker run --rm -i -v "${PWD}:/tmp/host" ghcr.io/${{ github.repository_owner }}/wasm-clang-builder:latest /opt/wasi-sdk/bin/clang -flto -ffunction-sections -mexec-model=reactor -O3 -z stack-size=4096 -Wl,--initial-memory=65536 -Wl,--export=__data_end -Wl,--export=__heap_base,--export=malloc,--export=free,--export=__wasm_call_ctors -Wl,--strip-all,--no-entry -Wl,--allow-undefined -Wl,--gc-sections -o /tmp/host/${FILENAME%.*}-wasi-libc.wasm /tmp/host/${FILENAME}
85-
cargo run -p hyperlight-wasm-aot compile ${FILENAME%.*}-wasi-libc.wasm ${FILENAME%.*}.aot
86-
cp ${FILENAME%.*}.aot ${FILENAME%.*}.wasm
87-
done
81+
just ensure-tools
82+
just build-wasm-examples release
8883
shell: bash
8984
working-directory: src/wasmsamples
9085
- name: Upload Wasm Modules
9186
uses: actions/upload-artifact@v4
9287
with:
9388
name: guest-modules
9489
path: |
95-
src/wasmsamples/*.wasm
96-
src/wasmsamples/*.aot
90+
x64/release/*.wasm
91+
x64/release/*.aot

.github/workflows/dep_rust.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ jobs:
8282
# this must be build before the formatting and other jobs run
8383
# because the component model example depends on the wasm component built here
8484
just ensure-tools
85+
just compile-wit
8586
just build-rust-component-examples ${{ matrix.config }}
8687
8788
- name: Fmt

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,3 +479,4 @@ target/
479479
# MSVC Windows builds of rustc generate these, which store debugging information
480480
*.pdb
481481
src/component_sample/**/*.wasm
482+
src/wasmsamples/components/bindings/

Cargo.lock

Lines changed: 3 additions & 72 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Justfile

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ build-wasm-examples-command := if os() == "windows" { "./src/hyperlight_wasm/scr
44
mkdir-arg := if os() == "windows" { "-Force" } else { "-p" }
55
latest-release:= if os() == "windows" {"$(git tag -l --sort=v:refname | select -last 2 | select -first 1)"} else {`git tag -l --sort=v:refname | tail -n 2 | head -n 1`}
66
wit-world := if os() == "windows" { "$env:WIT_WORLD=\"" + justfile_directory() + "\\src\\component_sample\\wit\\component-world.wasm" + "\";" } else { "WIT_WORLD=" + justfile_directory() + "/src/component_sample/wit/component-world.wasm" }
7+
wit-world-c := if os() == "windows" { "$env:WIT_WORLD=\"" + justfile_directory() + "\\src\\wasmsamples\\components\\runcomponent-world.wasm" + "\";" } else { "WIT_WORLD=" + justfile_directory() + "/src/wasmsamples/components/runcomponent-world.wasm" }
78

89
set windows-shell := ["pwsh.exe", "-NoLogo", "-Command"]
910

@@ -14,8 +15,9 @@ make-vendor-tar:
1415
-C ./src wasm_runtime hyperlight_wasm_macro
1516

1617
ensure-tools:
17-
cargo install --locked wasm-tools --version 1.235.0
18+
cargo install wasm-tools --locked --version 1.235.0
1819
cargo install cargo-component --locked --version 0.21.1
20+
cargo install wit-bindgen-cli --locked --version 0.43.0
1921

2022
build-all target=default-target: (build target) (build-wasm-examples target) (build-rust-wasm-examples target) (build-wasm-runtime target) (build-rust-component-examples target)
2123

@@ -26,10 +28,14 @@ mkdir-redist target=default-target:
2628
mkdir {{ mkdir-arg }} x64
2729
mkdir {{ mkdir-arg }} x64/{{ target }}
2830

31+
compile-wit:
32+
wasm-tools component wit ./src/wasmsamples/components/runcomponent.wit -w -o ./src/wasmsamples/components/runcomponent-world.wasm
33+
wasm-tools component wit ./src/component_sample/wit/example.wit -w -o ./src/component_sample/wit/component-world.wasm
34+
2935
build-wasm-runtime target=default-target:
3036
cd ./src/wasm_runtime && cargo build --verbose --profile={{ if target == "debug" {"dev"} else { target } }} && rm -R target
3137

32-
build-wasm-examples target=default-target:
38+
build-wasm-examples target=default-target: (compile-wit)
3339
{{ build-wasm-examples-command }} {{target}}
3440

3541
build-rust-wasm-examples target=default-target: (mkdir-redist target)
@@ -38,8 +44,7 @@ build-rust-wasm-examples target=default-target: (mkdir-redist target)
3844
cargo run -p hyperlight-wasm-aot compile ./src/rust_wasm_samples/target/wasm32-unknown-unknown/{{ target }}/rust_wasm_samples.wasm ./x64/{{ target }}/rust_wasm_samples.aot
3945
cp ./x64/{{ target }}/rust_wasm_samples.aot ./x64/{{ target }}/rust_wasm_samples.wasm
4046

41-
build-rust-component-examples target=default-target:
42-
wasm-tools component wit ./src/component_sample/wit/example.wit -w -o ./src/component_sample/wit/component-world.wasm
47+
build-rust-component-examples target=default-target: (compile-wit)
4348
# use cargo component so we don't get all the wasi imports https://github.com/bytecodealliance/cargo-component?tab=readme-ov-file#relationship-with-wasm32-wasip2
4449
# we also explicitly target wasm32-unknown-unknown since cargo component might try to pull in wasi imports https://github.com/bytecodealliance/cargo-component/issues/290
4550
rustup target add wasm32-unknown-unknown
@@ -101,10 +106,14 @@ examples-components target=default-target features="": (build-rust-component-exa
101106
{{ wit-world }} cargo run {{ if features =="" {''} else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example component_example
102107

103108
# warning, compares to and then OVERWRITES the given baseline
104-
bench-ci baseline target=default-target features="":
105-
cd src/hyperlight_wasm && cargo bench --profile={{ if target == "debug" {"dev"} else { target } }} {{ if features =="" {''} else { "--features " + features } }} -- --verbose --save-baseline {{baseline}}
106-
bench target=default-target features="":
107-
cd src/hyperlight_wasm && cargo bench --profile={{ if target == "debug" {"dev"} else { target } }} {{ if features =="" {''} else { "--features " + features } }} -- --verbose
109+
bench-ci baseline target="release" features="":
110+
cd src/hyperlight_wasm && cargo bench --profile={{ if target == "debug" {"dev"} else { target } }} {{ if features =="" {''} else { "--features " + features } }} --bench benchmarks -- --verbose --save-baseline {{baseline}}
111+
cd src/hyperlight_wasm; {{wit-world-c}} cargo bench --profile={{ if target == "debug" {"dev"} else { target } }} {{ if features =="" {''} else { "--features " + features } }} --bench benchmarks_components -- --verbose --save-baseline {{baseline}}-components
112+
bench target="release" features="": (bench-wasm target features) (bench-components target features)
113+
bench-wasm target="release" features="":
114+
cd src/hyperlight_wasm && cargo bench --profile={{ if target == "debug" {"dev"} else { target } }} {{ if features =="" {''} else { "--features " + features } }} --bench benchmarks -- --verbose
115+
bench-components target="release" features="":
116+
cd src/hyperlight_wasm; {{wit-world-c}} cargo bench --profile={{ if target == "debug" {"dev"} else { target } }} {{ if features =="" {''} else { "--features " + features } }} --bench benchmarks_components -- --verbose
108117
bench-download os hypervisor cpu tag="":
109118
gh release download {{ tag }} -D ./src/hyperlight_wasm/target/ -p benchmarks_{{ os }}_{{ hypervisor }}_{{ cpu }}.tar.gz
110119
mkdir {{ mkdir-arg }} ./src/hyperlight_wasm/target/criterion

src/hyperlight_wasm/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,8 @@ mshv3 = ["hyperlight-host/mshv3"]
8888
[[bench]]
8989
name = "benchmarks"
9090
harness = false
91+
92+
[[bench]]
93+
name = "benchmarks_components"
94+
harness = false
95+
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
use std::sync::{Arc, Mutex};
2+
3+
use criterion::{Bencher, Criterion, criterion_group, criterion_main};
4+
use hyperlight_wasm::{LoadedWasmSandbox, SandboxBuilder};
5+
6+
use crate::bindings::example::runcomponent::Guest;
7+
8+
extern crate alloc;
9+
mod bindings {
10+
hyperlight_component_macro::host_bindgen!(
11+
"../../src/wasmsamples/components/runcomponent-world.wasm"
12+
);
13+
}
14+
15+
pub struct State {}
16+
impl State {
17+
pub fn new() -> Self {
18+
State {}
19+
}
20+
}
21+
22+
impl Default for State {
23+
fn default() -> Self {
24+
Self::new()
25+
}
26+
}
27+
28+
impl bindings::example::runcomponent::Host for State {
29+
fn r#get_time_since_boot_microsecond(&mut self) -> i64 {
30+
let res = std::time::SystemTime::now()
31+
.duration_since(std::time::SystemTime::UNIX_EPOCH)
32+
.unwrap()
33+
.as_micros();
34+
i64::try_from(res).unwrap()
35+
}
36+
}
37+
38+
impl bindings::example::runcomponent::RuncomponentImports for State {
39+
type Host = State;
40+
41+
fn r#host(&mut self) -> impl ::core::borrow::BorrowMut<Self::Host> {
42+
self
43+
}
44+
}
45+
46+
fn wasm_component_guest_call_benchmark(c: &mut Criterion) {
47+
let mut group = c.benchmark_group("wasm_component_guest_functions");
48+
49+
let bench_guest_function = |b: &mut Bencher<'_>, ext| {
50+
let (sb, rt) = get_loaded_wasm_sandbox(ext);
51+
let mut wrapped = bindings::RuncomponentSandbox { sb, rt };
52+
let instance = bindings::example::runcomponent::RuncomponentExports::guest(&mut wrapped);
53+
54+
b.iter(|| {
55+
instance.echo("Hello World!".to_string());
56+
});
57+
};
58+
59+
group.bench_function("wasm_guest_call", |b: &mut Bencher<'_>| {
60+
bench_guest_function(b, "wasm");
61+
});
62+
63+
group.bench_function("wasm_guest_call_aot", |b: &mut Bencher<'_>| {
64+
bench_guest_function(b, "aot");
65+
});
66+
67+
group.finish();
68+
}
69+
70+
fn wasm_component_sandbox_benchmark(c: &mut Criterion) {
71+
let mut group = c.benchmark_group("wasm_component_sandboxes");
72+
let create_wasm_sandbox = || {
73+
get_loaded_wasm_sandbox("wasm");
74+
};
75+
76+
group.bench_function("create_sandbox", |b| {
77+
b.iter_with_large_drop(create_wasm_sandbox);
78+
});
79+
80+
group.bench_function("create_sandbox_and_drop", |b| {
81+
b.iter(create_wasm_sandbox);
82+
});
83+
84+
group.finish();
85+
}
86+
87+
fn get_loaded_wasm_sandbox(
88+
ext: &str,
89+
) -> (
90+
LoadedWasmSandbox,
91+
Arc<Mutex<bindings::RuncomponentResources<State>>>,
92+
) {
93+
let state = State::new();
94+
let mut sandbox = SandboxBuilder::new().build().unwrap();
95+
let rt = bindings::register_host_functions(&mut sandbox, state);
96+
97+
let sb = sandbox.load_runtime().unwrap();
98+
99+
let sb = sb
100+
.load_module(format!("../../x64/release/runcomponent.{ext}",))
101+
.unwrap();
102+
(sb, rt)
103+
}
104+
105+
criterion_group! {
106+
name = benches_components;
107+
config = Criterion::default();//.warm_up_time(Duration::from_millis(50)); // If warm_up_time is default 3s warmup, the benchmark will fail due memory error
108+
targets = wasm_component_guest_call_benchmark, wasm_component_sandbox_benchmark
109+
}
110+
criterion_main!(benches_components);

0 commit comments

Comments
 (0)