From dea93272b80a7ae658318ce7af21f00cacae054d Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Sat, 24 Feb 2024 14:35:20 +0100 Subject: pref: improve parser performance Signed-off-by: Henry Gressmann --- Cargo.lock | 20 +++++++------- crates/benchmarks/benches/selfhosted.rs | 18 ++++++++----- crates/parser/src/conversion.rs | 47 ++++++++++++++++++++++++--------- examples/rust/README.md | 2 ++ examples/rust/rust-toolchain.toml | 2 ++ 5 files changed, 61 insertions(+), 28 deletions(-) create mode 100644 examples/rust/rust-toolchain.toml diff --git a/Cargo.lock b/Cargo.lock index 8508a3a..fbfe381 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -280,9 +280,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" +checksum = "3286b845d0fccbdd15af433f61c5970e711987036cb468f437ff6badd70f4e24" [[package]] name = "cfg-if" @@ -649,9 +649,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.6" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c376d08ea6aa96aafe61237c7200d1241cb177b7d3a542d791f2d118e9cbb955" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ "darling_core", "darling_macro", @@ -659,9 +659,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.6" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33043dcd19068b8192064c704b3f83eb464f91f1ff527b44a4e2b08d9cdb8855" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", @@ -672,9 +672,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.6" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a91391accf613803c2a9bf9abccdbaa07c54b4244a5b64883f9c3c137c86be" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", @@ -1121,9 +1121,9 @@ dependencies = [ [[package]] name = "image" -version = "0.24.8" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" dependencies = [ "bytemuck", "byteorder", diff --git a/crates/benchmarks/benches/selfhosted.rs b/crates/benchmarks/benches/selfhosted.rs index b022fd1..985577c 100644 --- a/crates/benchmarks/benches/selfhosted.rs +++ b/crates/benchmarks/benches/selfhosted.rs @@ -53,13 +53,19 @@ fn run_wasmer(wasm: &[u8]) { const TINYWASM: &[u8] = include_bytes!("../../../examples/rust/out/tinywasm.wasm"); fn criterion_benchmark(c: &mut Criterion) { - let twasm = util::wasm_to_twasm(TINYWASM); + { + let mut group = c.benchmark_group("selfhosted-parse"); + group.bench_function("tinywasm", |b| b.iter(|| util::wasm_to_twasm(TINYWASM))); + } - let mut group = c.benchmark_group("selfhosted"); - group.bench_function("native", |b| b.iter(run_native)); - group.bench_function("tinywasm", |b| b.iter(|| run_tinywasm(&twasm))); - group.bench_function("wasmi", |b| b.iter(|| run_wasmi(TINYWASM))); - group.bench_function("wasmer", |b| b.iter(|| run_wasmer(TINYWASM))); + { + let twasm = util::wasm_to_twasm(TINYWASM); + let mut group = c.benchmark_group("selfhosted"); + // group.bench_function("native", |b| b.iter(run_native)); + group.bench_function("tinywasm", |b| b.iter(|| run_tinywasm(&twasm))); + // group.bench_function("wasmi", |b| b.iter(|| run_wasmi(TINYWASM))); + // group.bench_function("wasmer", |b| b.iter(|| run_wasmer(TINYWASM))); + } } criterion_group!( diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index 38a2ada..cd8840a 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -163,7 +163,7 @@ pub(crate) fn convert_module_code( } let body_reader = func.get_operators_reader()?; - let body = process_operators(body_reader.original_position(), body_reader.into_iter(), validator)?; + let body = process_operators(body_reader, validator)?; Ok(CodeSection { locals: locals.into_boxed_slice(), body }) } @@ -228,28 +228,47 @@ pub(crate) fn process_const_operator(op: wasmparser::Operator<'_>) -> Result( - mut offset: usize, - ops: impl Iterator, wasmparser::BinaryReaderError>>, +pub(crate) fn process_operators( + ops: OperatorsReader<'_>, mut validator: FuncValidator, ) -> Result> { - let mut instructions = Vec::new(); - let mut labels_ptrs = Vec::new(); // indexes into the instructions array + let mut instructions = Vec::with_capacity(1024); + let mut labels_ptrs = Vec::with_capacity(32); + // indexes into the instructions array + let mut offset = ops.original_position(); for op in ops { - log::debug!("op: {:?}", op); + let op = match op { + Ok(op) => op, + Err(e) => { + cold(); + log::error!("Error while processing operators: {:?}", e); + return Err(crate::ParseError::UnsupportedOperator("Error while processing operators".to_string())); + } + }; - let op = op?; - validator.op(offset, &op)?; + match validator.op(offset, &op) { + Ok(_) => (), + Err(e) => { + cold(); + log::error!("Error while processing operators: {:?}", e); + return Err(crate::ParseError::UnsupportedOperator("Error while processing operators".to_string())); + } + } offset += 1; use wasmparser::Operator::*; let res = match op { BrTable { targets } => { let def = targets.default(); - let targets = targets.targets().collect::, wasmparser::BinaryReaderError>>()?; - instructions.push(Instruction::BrTable(def, targets.len())); - instructions.extend(targets.into_iter().map(Instruction::BrLabel)); + + let instrs = targets + .targets() + .map(|t| t.map(Instruction::BrLabel)) + .collect::, wasmparser::BinaryReaderError>>()?; + + instructions.push(Instruction::BrTable(def, instrs.len())); + instructions.extend(instrs); continue; } Unreachable => Instruction::Unreachable, @@ -510,6 +529,7 @@ pub(crate) fn process_operators<'a>( TableSize { table } => Instruction::TableSize(table), TableFill { table } => Instruction::TableFill(table), op => { + cold(); log::error!("Unsupported instruction: {:?}", op); return Err(crate::ParseError::UnsupportedOperator(format!("Unsupported instruction: {:?}", op))); } @@ -524,3 +544,6 @@ pub(crate) fn process_operators<'a>( validator.finish(offset)?; Ok(instructions.into_boxed_slice()) } + +#[cold] +fn cold() {} diff --git a/examples/rust/README.md b/examples/rust/README.md index 1b6be2f..c24054c 100644 --- a/examples/rust/README.md +++ b/examples/rust/README.md @@ -2,3 +2,5 @@ This is a seperate crate that generates WebAssembly from Rust code. It is used by the `wasm-rust` example. + +Requires the `wasm32-unknown-unknown` target to be installed. diff --git a/examples/rust/rust-toolchain.toml b/examples/rust/rust-toolchain.toml new file mode 100644 index 0000000..6c22ba5 --- /dev/null +++ b/examples/rust/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel="nightly-2024-02-11" -- cgit v1.3.1