From c31498b8ccf3ef0a4dd9180e22df4b4e8595fe08 Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Mon, 18 Jun 2018 18:09:54 +0300 Subject: [PATCH] Add redux_regex test. # Conflicts: # benches/wasm-kernel/Cargo.toml --- benches/Cargo.toml | 1 + benches/src/lib.rs | 49 ++++++++++++++++++++++++-- benches/wasm-kernel/Cargo.toml | 3 +- benches/wasm-kernel/src/lib.rs | 49 ++++++++++++++++++++++---- benches/wasm-kernel/src/regex_redux.rs | 18 ++++++++++ 5 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 benches/wasm-kernel/src/regex_redux.rs diff --git a/benches/Cargo.toml b/benches/Cargo.toml index 0df6e79..3626446 100644 --- a/benches/Cargo.toml +++ b/benches/Cargo.toml @@ -6,3 +6,4 @@ authors = ["Sergey Pepyakin "] [dependencies] wasmi = { path = ".." } assert_matches = "1.2" +wabt = "0.3" diff --git a/benches/src/lib.rs b/benches/src/lib.rs index 859a06c..8eead71 100644 --- a/benches/src/lib.rs +++ b/benches/src/lib.rs @@ -4,6 +4,7 @@ extern crate test; extern crate wasmi; #[macro_use] extern crate assert_matches; +extern crate wabt; use std::error; use std::fs::File; @@ -95,11 +96,55 @@ fn bench_rev_comp(b: &mut Bencher) { "", ); let result = memory - .get(output_data_mem_offset, REVCOMP_INPUT.len()) + .get(output_data_mem_offset, REVCOMP_OUTPUT.len()) .expect("can't get result data from a wasm memory"); assert_eq!(&*result, REVCOMP_OUTPUT); } +#[bench] +fn bench_regex_redux(b: &mut Bencher) { + let wasm_kernel = load_from_file( + "./wasm-kernel/target/wasm32-unknown-unknown/release/wasm_kernel.wasm", + ).expect("failed to load wasm_kernel. Is `build.rs` broken?"); + + let instance = ModuleInstance::new(&wasm_kernel, &ImportsBuilder::default()) + .expect("failed to instantiate wasm module") + .assert_no_start(); + + // Allocate buffers for the input and output. + let test_data_ptr: RuntimeValue = { + let input_size = RuntimeValue::I32(REVCOMP_INPUT.len() as i32); + assert_matches!( + instance.invoke_export("prepare_regex_redux", &[input_size], &mut NopExternals), + Ok(Some(v @ RuntimeValue::I32(_))) => v, + "", + ) + }; + + // Get the pointer to the input buffer. + let input_data_mem_offset = assert_matches!( + instance.invoke_export("regex_redux_input_ptr", &[test_data_ptr], &mut NopExternals), + Ok(Some(RuntimeValue::I32(v))) => v as u32, + "", + ); + + // Copy test data inside the wasm memory. + let memory = instance.export_by_name("memory") + .expect("Expected export with a name 'memory'") + .as_memory() + .expect("'memory' should be a memory instance") + .clone(); + memory + .set(input_data_mem_offset, REVCOMP_INPUT) + .expect("can't load test data into a wasm memory"); + + b.iter(|| { + instance + .invoke_export("bench_regex_redux", &[test_data_ptr], &mut NopExternals) + .unwrap(); + }); +} + #[bench] fn fac_recursive(b: &mut Bencher) { let wasm = wabt::wat2wasm( @@ -193,7 +238,7 @@ fn recursive_ok(b: &mut Bencher) { b.iter(|| { let value = instance - .invoke_export("call", &[RuntimeValue::I32(9999)], &mut NopExternals); + .invoke_export("call", &[RuntimeValue::I32(8000)], &mut NopExternals); assert_matches!(value, Ok(Some(RuntimeValue::I32(0)))); }); } diff --git a/benches/wasm-kernel/Cargo.toml b/benches/wasm-kernel/Cargo.toml index f9717f5..f6ea6dc 100644 --- a/benches/wasm-kernel/Cargo.toml +++ b/benches/wasm-kernel/Cargo.toml @@ -8,7 +8,8 @@ crate-type = ["cdylib"] [dependencies] tiny-keccak = "1.4.2" -rlibc = "1.0" +regex = "0.2.10" +lazy_static = "1.0" [profile.release] panic = "abort" diff --git a/benches/wasm-kernel/src/lib.rs b/benches/wasm-kernel/src/lib.rs index bfd9ad4..7bed756 100644 --- a/benches/wasm-kernel/src/lib.rs +++ b/benches/wasm-kernel/src/lib.rs @@ -1,14 +1,12 @@ -#![no_std] -#![feature(lang_items)] -#![feature(core_intrinsics)] -#![feature(panic_implementation)] - -extern crate rlibc; extern crate tiny_keccak; +extern crate regex; +#[macro_use] +extern crate lazy_static; use tiny_keccak::Keccak; mod rev_complement; +mod regex_redux; pub struct TinyKeccakTestData { data: &'static [u8], @@ -74,7 +72,7 @@ pub extern "C" fn rev_complement_input_ptr(test_data: *mut RevComplementTestData #[no_mangle] pub extern "C" fn rev_complement_output_ptr(test_data: *mut RevComplementTestData) -> *const u8 { unsafe { - (*test_data).output.as_mut_ptr() + (*test_data).output.as_ptr() } } @@ -85,3 +83,40 @@ pub extern "C" fn bench_rev_complement(test_data: *mut RevComplementTestData) { (*test_data).output.copy_from_slice(&result); } } + +pub struct RegexReduxTestData { + input: Box<[u8]>, + output: Option, +} + +#[no_mangle] +pub extern "C" fn prepare_regex_redux(size: usize) -> *mut RegexReduxTestData { + regex_redux::prepare(); + + let input = vec![0; size]; + let test_data = Box::new( + RegexReduxTestData { + input: input.into_boxed_slice(), + output: None, + } + ); + + // Basically leak the pointer to the test data. This shouldn't be harmful since `prepare` is called + // only once per bench run (not for the iteration), and afterwards whole memory instance is discarded. + Box::into_raw(test_data) +} + +#[no_mangle] +pub extern "C" fn regex_redux_input_ptr(test_data: *mut RegexReduxTestData) -> *mut u8 { + unsafe { + (*test_data).input.as_mut_ptr() + } +} + +#[no_mangle] +pub extern "C" fn bench_regex_redux(test_data: *mut RegexReduxTestData) { + unsafe { + let result = regex_redux::run(&*(*test_data).input); + (*test_data).output = Some(result); + } +} diff --git a/benches/wasm-kernel/src/regex_redux.rs b/benches/wasm-kernel/src/regex_redux.rs new file mode 100644 index 0000000..7b31667 --- /dev/null +++ b/benches/wasm-kernel/src/regex_redux.rs @@ -0,0 +1,18 @@ +//! Initially it supposed to be like [1]. However it turned out +//! that executing this code in wasmi way too slow. +//! +//! [1]: https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/regexredux-rust-2.html + +lazy_static! { + static ref REGEX: ::regex::bytes::Regex = { + ::regex::bytes::Regex::new("agggtaa[cgt]|[acg]ttaccct").unwrap() + }; +} + +pub fn prepare() { + ®EX; +} + +pub fn run(seq: &[u8]) -> usize { + REGEX.find_iter(seq).count() +}