diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 927bdbc6a6..09c2864746 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -42,6 +42,7 @@ jobs: --exclude wasmi_fuzz --exclude wasmi_benches_tiny_keccak --exclude wasmi_benches_reverse_complement + --exclude wasmi_benches_regex_redux - name: Build (wasm32) run: >- cargo build @@ -56,6 +57,7 @@ jobs: --exclude wasmi_fuzz --exclude wasmi_benches_tiny_keccak --exclude wasmi_benches_reverse_complement + --exclude wasmi_benches_regex_redux test-asan: name: Test (Address Sanitizer) diff --git a/Cargo.lock b/Cargo.lock index 7673d2acb7..c4f5d12b04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1873,6 +1873,13 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" +[[package]] +name = "wasmi_benches_regex_redux" +version = "0.0.0" +dependencies = [ + "regex", +] + [[package]] name = "wasmi_benches_reverse_complement" version = "0.0.0" diff --git a/Cargo.toml b/Cargo.toml index cf8029b546..3f0854cc41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "crates/wasi", "crates/wasmi/benches/rust/tiny_keccak", "crates/wasmi/benches/rust/reverse_complement", + "crates/wasmi/benches/rust/regex_redux", "fuzz", ] exclude = [] diff --git a/crates/wasmi/benches/benches.rs b/crates/wasmi/benches/benches.rs index 5dbf20e900..ee32c30b17 100644 --- a/crates/wasmi/benches/benches.rs +++ b/crates/wasmi/benches/benches.rs @@ -768,20 +768,20 @@ fn bench_execute_rev_comp(c: &mut Criterion) { fn bench_execute_regex_redux(c: &mut Criterion) { c.bench_function("execute/regex_redux", |b| { - let (mut store, instance) = load_instance_from_file(WASM_KERNEL); + let (mut store, instance) = load_instance_from_file("benches/rust/regex_redux.wasm"); // Allocate buffers for the input and output. - let test_data_ptr = instance - .get_typed_func::(&store, "prepare_regex_redux") + let data_ptr = instance + .get_typed_func::(&store, "setup") .unwrap() .call(&mut store, REVCOMP_INPUT.len() as i32) .unwrap(); // Get the pointer to the input buffer. let input_data_mem_offset = instance - .get_typed_func::(&store, "regex_redux_input_ptr") + .get_typed_func::(&store, "input_ptr") .unwrap() - .call(&mut store, test_data_ptr) + .call(&mut store, data_ptr) .unwrap(); // Copy test data inside the wasm memory. @@ -792,12 +792,25 @@ fn bench_execute_regex_redux(c: &mut Criterion) { .unwrap(); // Actually run the benchmark: - let run = instance - .get_typed_func::(&store, "bench_regex_redux") - .unwrap(); + let run = instance.get_typed_func::(&store, "run").unwrap(); b.iter(|| { - run.call(&mut store, test_data_ptr).unwrap(); - }) + run.call(&mut store, data_ptr).unwrap(); + }); + + // Check the result of the regex find. + let result = instance + .get_typed_func::(&store, "output") + .unwrap() + .call(&mut store, data_ptr) + .unwrap(); + assert_eq!(result, 2); + + // Teardown benchmark data. + instance + .get_typed_func::(&store, "teardown") + .unwrap() + .call(&mut store, data_ptr) + .unwrap(); }); } diff --git a/crates/wasmi/benches/rust/regex_redux.wasm b/crates/wasmi/benches/rust/regex_redux.wasm new file mode 100644 index 0000000000..26a47817ad Binary files /dev/null and b/crates/wasmi/benches/rust/regex_redux.wasm differ diff --git a/crates/wasmi/benches/rust/regex_redux/Cargo.toml b/crates/wasmi/benches/rust/regex_redux/Cargo.toml new file mode 100644 index 0000000000..015218debd --- /dev/null +++ b/crates/wasmi/benches/rust/regex_redux/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "wasmi_benches_regex_redux" +version = "0.0.0" +publish = false +authors.workspace = true +edition.workspace = true + +[lib] +path = "lib.rs" +crate-type = ["cdylib"] + +[dependencies] +regex = "1.10.5" diff --git a/crates/wasmi/benches/rust/regex_redux/README.md b/crates/wasmi/benches/rust/regex_redux/README.md new file mode 100644 index 0000000000..9904c07f91 --- /dev/null +++ b/crates/wasmi/benches/rust/regex_redux/README.md @@ -0,0 +1,35 @@ +## Benchmark - Regex Redux + +Rust based `regex_redux` benchmark test case. + +Build with + +``` +cargo build \ + --package wasmi_benches_regex_redux \ + --profile wasm \ + --target wasm32-unknown-unknown +``` + +Post-optimize with `wasm-opt` using: + +``` +wasm-opt \ + -O3 \ + target/wasm32-unknown-unknown/wasm/wasmi_benches_regex_redux.wasm \ + -o target/wasm32-unknown-unknown/wasm/wasmi_benches_regex_redux.opt.wasm +``` + +Finally move the post-optimized Wasm binary into the proper place: + +``` +cp \ + target/wasm32-unknown-unknown/wasm/wasmi_benches_regex_redux.opt.wasm \ + crates/wasmi/benches/rust/regex_redux.wasm +``` + +Benchmark with: + +``` +cargo bench --bench benches execute/regex_redux +``` diff --git a/crates/wasmi/benches/rust/regex_redux/lib.rs b/crates/wasmi/benches/rust/regex_redux/lib.rs new file mode 100644 index 0000000000..0d873ed52c --- /dev/null +++ b/crates/wasmi/benches/rust/regex_redux/lib.rs @@ -0,0 +1,44 @@ +//! Initially it was supposed to be like [1]. However it turned out +//! that executing this code in Wasmi way too slow, unfortunately. +//! +//! [1]: https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/regexredux-rust-2.html + +use regex::bytes::Regex; + +#[repr(C)] +pub struct RegexReduxData { + regex: Regex, + input: Box<[u8]>, + output: Option, +} + +#[no_mangle] +pub extern "C" fn setup(size: usize) -> Box { + Box::new(RegexReduxData { + regex: Regex::new("agggtaa[cgt]|[acg]ttaccct").unwrap(), + input: vec![0; size].into(), + output: None, + }) +} + +#[no_mangle] +pub extern "C" fn teardown(_: Box) {} + +#[no_mangle] +pub extern "C" fn input_ptr(data: &mut RegexReduxData) -> *mut u8 { + data.input.as_mut_ptr() +} + +#[no_mangle] +pub extern "C" fn output(data: &mut RegexReduxData) -> u32 { + match data.output { + Some(output) => output.try_into().unwrap(), + None => u32::MAX, + } +} + +#[no_mangle] +pub extern "C" fn run(data: &mut RegexReduxData) { + let result: usize = data.regex.find_iter(&data.input[..]).count(); + data.output = Some(result); +}