From 2afed487ed29565cf5363dd3f5e2d6e26f2894b8 Mon Sep 17 00:00:00 2001 From: Bo Yao Date: Wed, 10 Nov 2021 10:59:59 +0800 Subject: [PATCH 1/5] slow compile repro --- Cargo.lock | 74 ++++++++++++++++++++++++++++++- Cargo.toml | 1 + examples/compiler_singlepass.rs | 77 +++++++++++++++++++++++---------- 3 files changed, 128 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7abf5a54310..d8cadc753e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,6 +52,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anyhow" version = "1.0.42" @@ -277,6 +286,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "winapi", +] + [[package]] name = "clang-sys" version = "1.2.0" @@ -294,7 +315,7 @@ version = "2.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ - "ansi_term", + "ansi_term 0.11.0", "atty", "bitflags", "strsim 0.8.0", @@ -1337,6 +1358,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.14" @@ -1541,7 +1572,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" dependencies = [ - "ansi_term", + "ansi_term 0.11.0", "ctor", "difference", "output_vt100", @@ -2385,19 +2416,57 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "tracing-log" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-span-tree" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877726b1570d7764022ef20cc61479b5bcfc1118b90521ce61f6cc9e4f5ffbd8" +dependencies = [ + "tracing", + "tracing-subscriber", +] + [[package]] name = "tracing-subscriber" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab69019741fca4d98be3c62d2b75254528b5432233fd8a4d2739fec20278de48" dependencies = [ + "ansi_term 0.12.1", + "chrono", "lazy_static", "matchers", "regex", + "serde", + "serde_json", "sharded-slab", + "smallvec", "thread_local", "tracing", "tracing-core", + "tracing-log", + "tracing-serde", ] [[package]] @@ -3136,6 +3205,7 @@ dependencies = [ "test-env-log", "test-generator", "tracing", + "tracing-span-tree", "tracing-subscriber", "wasi-test-generator", "wasmer", diff --git a/Cargo.toml b/Cargo.toml index 44449c8945e..5878b2019a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ wasmer-cache = { version = "2.0.0", path = "lib/cache", optional = true } wasmer-types = { version = "2.0.0", path = "lib/types" } wasmer-middlewares = { version = "2.0.0", path = "lib/middlewares", optional = true } cfg-if = "1.0" +tracing-span-tree = "0.1" [workspace] members = [ diff --git a/examples/compiler_singlepass.rs b/examples/compiler_singlepass.rs index 845b9db302c..fe93c2c9faa 100644 --- a/examples/compiler_singlepass.rs +++ b/examples/compiler_singlepass.rs @@ -10,24 +10,40 @@ //! //! Ready? +use std::fmt::Write; use wasmer::{imports, wat2wasm, Instance, Module, Store, Value}; use wasmer_compiler_singlepass::Singlepass; use wasmer_engine_universal::Universal; +pub fn many_functions_contract(function_count: u32) -> Vec { + let mut functions = String::new(); + for i in 0..function_count { + writeln!( + &mut functions, + "(func + i32.const {} + drop + return)", + i + ) + .unwrap(); + } + + let code = format!( + r#"(module + (export "main" (func 0)) + {})"#, + functions + ); + wat2wasm(code.as_bytes()).unwrap().to_vec() +} + fn main() -> Result<(), Box> { + tracing_span_tree::span_tree().aggregate(true).enable(); + // Let's declare the Wasm module with the text representation. - let wasm_bytes = wat2wasm( - r#" -(module - (type $sum_t (func (param i32 i32) (result i32))) - (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - local.get $x - local.get $y - i32.add) - (export "sum" (func $sum_f))) -"# - .as_bytes(), - )?; + let wasm_bytes = many_functions_contract(150_000); + println!("code.len() = {:?}", wasm_bytes.len() / 1024); // Use Singlepass compiler with the default settings let compiler = Singlepass::default(); @@ -37,24 +53,41 @@ fn main() -> Result<(), Box> { println!("Compiling module..."); // Let's compile the Wasm module. - let module = Module::new(&store, wasm_bytes)?; + // let guard = pprof::ProfilerGuard::new(100).unwrap(); + let module = { + let _span = tracing::debug_span!(target: "vm", "Module::new (compile)").entered(); + + Module::new(&store, wasm_bytes)? + }; + // if let Ok(report) = guard.report().build() { + // // println!("report: {:?}", &report); + // let file = std::fs::File::create("flamegraph2.svg").unwrap(); + // report.flamegraph(file).unwrap(); + // }; // Create an empty import object. let import_object = imports! {}; println!("Instantiating module..."); - // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = { + // Let's instantiate the Wasm module. + let _span = tracing::debug_span!(target: "vm", "Instance::new").entered(); + Instance::new(&module, &import_object)? + }; - let sum = instance.exports.get_function("sum")?; + println!("Instantiating module... the second time"); + let instance = { + // This one matches NEAR's execution model of initialization + let _span = tracing::debug_span!(target: "vm", "Instance::new").entered(); + Instance::new(&module, &import_object)? + }; + let main = instance.exports.get_function("main")?; - println!("Calling `sum` function..."); - // Let's call the `sum` exported function. The parameters are a - // slice of `Value`s. The results are a boxed slice of `Value`s. - let results = sum.call(&[Value::I32(1), Value::I32(2)])?; + println!("Calling `main` function..."); + let results = main.call(&[])?; println!("Results: {:?}", results); - assert_eq!(results.to_vec(), vec![Value::I32(3)]); + // assert_eq!(results.to_vec(), vec![Value::I32(3)]); Ok(()) } @@ -63,4 +96,4 @@ fn main() -> Result<(), Box> { #[cfg(feature = "singlepass")] fn test_compiler_singlepass() -> Result<(), Box> { main() -} +} \ No newline at end of file From a925e0a67496c5f8fc2ff25f48bb639a334b1b2d Mon Sep 17 00:00:00 2001 From: Bo Yao Date: Wed, 10 Nov 2021 11:00:14 +0800 Subject: [PATCH 2/5] fix slow compilation by using dynasm VecAssembler --- lib/compiler-singlepass/src/codegen_x64.rs | 12 +++++++----- lib/compiler-singlepass/src/emitter_x64.rs | 4 +++- lib/compiler-singlepass/src/machine.rs | 4 +++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/compiler-singlepass/src/codegen_x64.rs b/lib/compiler-singlepass/src/codegen_x64.rs index beaefaaf389..d44f3be569d 100644 --- a/lib/compiler-singlepass/src/codegen_x64.rs +++ b/lib/compiler-singlepass/src/codegen_x64.rs @@ -1,6 +1,6 @@ use crate::address_map::get_function_address_map; use crate::{common_decl::*, config::Singlepass, emitter_x64::*, machine::Machine, x64_decl::*}; -use dynasmrt::{x64::Assembler, DynamicLabel}; +use dynasmrt::{x64::X64Relocation, DynamicLabel, VecAssembler}; use smallvec::{smallvec, SmallVec}; use std::collections::BTreeMap; use std::iter; @@ -22,6 +22,8 @@ use wasmer_types::{ }; use wasmer_vm::{MemoryStyle, TableStyle, TrapCode, VMBuiltinFunctionIndex, VMOffsets}; +type Assembler = VecAssembler; + /// The singlepass per-function code generator. pub struct FuncGen<'a> { // Immutable properties assigned at creation time. @@ -1844,7 +1846,7 @@ impl<'a> FuncGen<'a> { .collect(), ); - let mut assembler = Assembler::new().unwrap(); + let mut assembler = Assembler::new(0); let special_labels = SpecialLabelSet { integer_division_by_zero: assembler.get_label(), heap_access_oob: assembler.get_label(), @@ -8811,7 +8813,7 @@ pub fn gen_std_trampoline( sig: &FunctionType, calling_convention: CallingConvention, ) -> FunctionBody { - let mut a = Assembler::new().unwrap(); + let mut a = Assembler::new(0); // Calculate stack offset. let mut stack_offset: u32 = 0; @@ -8921,7 +8923,7 @@ pub fn gen_std_dynamic_import_trampoline( sig: &FunctionType, calling_convention: CallingConvention, ) -> FunctionBody { - let mut a = Assembler::new().unwrap(); + let mut a = Assembler::new(0); // Allocate argument array. let stack_offset: usize = 16 * std::cmp::max(sig.params().len(), sig.results().len()) + 8; // 16 bytes each + 8 bytes sysv call padding @@ -9043,7 +9045,7 @@ pub fn gen_import_call_trampoline( sig: &FunctionType, calling_convention: CallingConvention, ) -> CustomSection { - let mut a = Assembler::new().unwrap(); + let mut a = Assembler::new(0); // TODO: ARM entry trampoline is not emitted. diff --git a/lib/compiler-singlepass/src/emitter_x64.rs b/lib/compiler-singlepass/src/emitter_x64.rs index 7bd3d77927a..4a2d1601182 100644 --- a/lib/compiler-singlepass/src/emitter_x64.rs +++ b/lib/compiler-singlepass/src/emitter_x64.rs @@ -1,6 +1,8 @@ pub use crate::x64_decl::{GPR, XMM}; use dynasm::dynasm; -use dynasmrt::{x64::Assembler, AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi}; +use dynasmrt::{x64::X64Relocation, AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi, VecAssembler}; + +type Assembler = VecAssembler; /// Force `dynasm!` to use the correct arch (x64) when cross-compiling. /// `dynasm!` proc-macro tries to auto-detect it by default by looking at the diff --git a/lib/compiler-singlepass/src/machine.rs b/lib/compiler-singlepass/src/machine.rs index 73f75bc7be0..045bb8387f5 100644 --- a/lib/compiler-singlepass/src/machine.rs +++ b/lib/compiler-singlepass/src/machine.rs @@ -586,7 +586,9 @@ impl Machine { #[cfg(test)] mod test { use super::*; - use dynasmrt::x64::Assembler; + use dynasmrt::x64::X64Relocation; + use dynasmrt::VecAssembler; + type Assembler = VecAssembler; #[test] fn test_release_locations_keep_state_nopanic() { From c37a873b65798f7968e2da03a6f382cb7e1965ef Mon Sep 17 00:00:00 2001 From: Bo Yao Date: Mon, 15 Nov 2021 10:27:33 +0800 Subject: [PATCH 3/5] undo changes for bench --- Cargo.lock | 74 +------------------------------ Cargo.toml | 1 - examples/compiler_singlepass.rs | 77 ++++++++++----------------------- 3 files changed, 24 insertions(+), 128 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d8cadc753e8..7abf5a54310 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,15 +52,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "anyhow" version = "1.0.42" @@ -286,18 +277,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "libc", - "num-integer", - "num-traits", - "winapi", -] - [[package]] name = "clang-sys" version = "1.2.0" @@ -315,7 +294,7 @@ version = "2.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ - "ansi_term 0.11.0", + "ansi_term", "atty", "bitflags", "strsim 0.8.0", @@ -1358,16 +1337,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" -[[package]] -name = "num-integer" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" -dependencies = [ - "autocfg", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.14" @@ -1572,7 +1541,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" dependencies = [ - "ansi_term 0.11.0", + "ansi_term", "ctor", "difference", "output_vt100", @@ -2416,57 +2385,19 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "tracing-log" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" -dependencies = [ - "lazy_static", - "log", - "tracing-core", -] - -[[package]] -name = "tracing-serde" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" -dependencies = [ - "serde", - "tracing-core", -] - -[[package]] -name = "tracing-span-tree" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877726b1570d7764022ef20cc61479b5bcfc1118b90521ce61f6cc9e4f5ffbd8" -dependencies = [ - "tracing", - "tracing-subscriber", -] - [[package]] name = "tracing-subscriber" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab69019741fca4d98be3c62d2b75254528b5432233fd8a4d2739fec20278de48" dependencies = [ - "ansi_term 0.12.1", - "chrono", "lazy_static", "matchers", "regex", - "serde", - "serde_json", "sharded-slab", - "smallvec", "thread_local", "tracing", "tracing-core", - "tracing-log", - "tracing-serde", ] [[package]] @@ -3205,7 +3136,6 @@ dependencies = [ "test-env-log", "test-generator", "tracing", - "tracing-span-tree", "tracing-subscriber", "wasi-test-generator", "wasmer", diff --git a/Cargo.toml b/Cargo.toml index 5878b2019a8..44449c8945e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,6 @@ wasmer-cache = { version = "2.0.0", path = "lib/cache", optional = true } wasmer-types = { version = "2.0.0", path = "lib/types" } wasmer-middlewares = { version = "2.0.0", path = "lib/middlewares", optional = true } cfg-if = "1.0" -tracing-span-tree = "0.1" [workspace] members = [ diff --git a/examples/compiler_singlepass.rs b/examples/compiler_singlepass.rs index fe93c2c9faa..845b9db302c 100644 --- a/examples/compiler_singlepass.rs +++ b/examples/compiler_singlepass.rs @@ -10,40 +10,24 @@ //! //! Ready? -use std::fmt::Write; use wasmer::{imports, wat2wasm, Instance, Module, Store, Value}; use wasmer_compiler_singlepass::Singlepass; use wasmer_engine_universal::Universal; -pub fn many_functions_contract(function_count: u32) -> Vec { - let mut functions = String::new(); - for i in 0..function_count { - writeln!( - &mut functions, - "(func - i32.const {} - drop - return)", - i - ) - .unwrap(); - } - - let code = format!( - r#"(module - (export "main" (func 0)) - {})"#, - functions - ); - wat2wasm(code.as_bytes()).unwrap().to_vec() -} - fn main() -> Result<(), Box> { - tracing_span_tree::span_tree().aggregate(true).enable(); - // Let's declare the Wasm module with the text representation. - let wasm_bytes = many_functions_contract(150_000); - println!("code.len() = {:?}", wasm_bytes.len() / 1024); + let wasm_bytes = wat2wasm( + r#" +(module + (type $sum_t (func (param i32 i32) (result i32))) + (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) + local.get $x + local.get $y + i32.add) + (export "sum" (func $sum_f))) +"# + .as_bytes(), + )?; // Use Singlepass compiler with the default settings let compiler = Singlepass::default(); @@ -53,41 +37,24 @@ fn main() -> Result<(), Box> { println!("Compiling module..."); // Let's compile the Wasm module. - // let guard = pprof::ProfilerGuard::new(100).unwrap(); - let module = { - let _span = tracing::debug_span!(target: "vm", "Module::new (compile)").entered(); - - Module::new(&store, wasm_bytes)? - }; - // if let Ok(report) = guard.report().build() { - // // println!("report: {:?}", &report); - // let file = std::fs::File::create("flamegraph2.svg").unwrap(); - // report.flamegraph(file).unwrap(); - // }; + let module = Module::new(&store, wasm_bytes)?; // Create an empty import object. let import_object = imports! {}; println!("Instantiating module..."); - let instance = { - // Let's instantiate the Wasm module. - let _span = tracing::debug_span!(target: "vm", "Instance::new").entered(); - Instance::new(&module, &import_object)? - }; + // Let's instantiate the Wasm module. + let instance = Instance::new(&module, &import_object)?; - println!("Instantiating module... the second time"); - let instance = { - // This one matches NEAR's execution model of initialization - let _span = tracing::debug_span!(target: "vm", "Instance::new").entered(); - Instance::new(&module, &import_object)? - }; - let main = instance.exports.get_function("main")?; + let sum = instance.exports.get_function("sum")?; - println!("Calling `main` function..."); - let results = main.call(&[])?; + println!("Calling `sum` function..."); + // Let's call the `sum` exported function. The parameters are a + // slice of `Value`s. The results are a boxed slice of `Value`s. + let results = sum.call(&[Value::I32(1), Value::I32(2)])?; println!("Results: {:?}", results); - // assert_eq!(results.to_vec(), vec![Value::I32(3)]); + assert_eq!(results.to_vec(), vec![Value::I32(3)]); Ok(()) } @@ -96,4 +63,4 @@ fn main() -> Result<(), Box> { #[cfg(feature = "singlepass")] fn test_compiler_singlepass() -> Result<(), Box> { main() -} \ No newline at end of file +} From ff3b459e5b384b7c32ebd0d3964099dc641f8bb0 Mon Sep 17 00:00:00 2001 From: Bo Yao Date: Mon, 15 Nov 2021 15:33:22 +0800 Subject: [PATCH 4/5] fix --- lib/compiler-singlepass/src/machine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compiler-singlepass/src/machine.rs b/lib/compiler-singlepass/src/machine.rs index 045bb8387f5..36f66b60e96 100644 --- a/lib/compiler-singlepass/src/machine.rs +++ b/lib/compiler-singlepass/src/machine.rs @@ -593,7 +593,7 @@ mod test { #[test] fn test_release_locations_keep_state_nopanic() { let mut machine = Machine::new(); - let mut assembler = Assembler::new().unwrap(); + let mut assembler = Assembler::new(0); let locs = machine.acquire_locations( &mut assembler, &(0..10) From efb1f745bd29e6f1b6fc52baf3e7f63dfe3e69f6 Mon Sep 17 00:00:00 2001 From: Bo Yao Date: Tue, 16 Nov 2021 12:42:46 +0800 Subject: [PATCH 5/5] cargo fmt --all --- lib/compiler-singlepass/src/emitter_x64.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/compiler-singlepass/src/emitter_x64.rs b/lib/compiler-singlepass/src/emitter_x64.rs index 4a2d1601182..6ed4a7412b0 100644 --- a/lib/compiler-singlepass/src/emitter_x64.rs +++ b/lib/compiler-singlepass/src/emitter_x64.rs @@ -1,6 +1,8 @@ pub use crate::x64_decl::{GPR, XMM}; use dynasm::dynasm; -use dynasmrt::{x64::X64Relocation, AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi, VecAssembler}; +use dynasmrt::{ + x64::X64Relocation, AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi, VecAssembler, +}; type Assembler = VecAssembler;