From cbabcacb0f07eadbd012a00fd8cf7bc308b2f421 Mon Sep 17 00:00:00 2001 From: Sergei Shulepov Date: Tue, 10 Aug 2021 21:09:15 +0200 Subject: [PATCH] wasmtime: Option to disable parallel compilation (#3169) * Introduce parallel-compilation configuration switch * Plumb parallel_compilation config to compilation * Adjust obj.rs * Address review * Fix compilation fail in `cache` crate * Fix obj.rs Also remove the now unneeded feature in /Cargo.toml * fmt --- crates/cache/src/lib.rs | 2 ++ crates/jit/src/compiler.rs | 39 ++++++++++++++++++--- crates/jit/src/instantiate.rs | 19 +++++----- crates/jit/src/lib.rs | 14 -------- crates/wasmtime/src/config.rs | 22 +++++++++++- crates/wasmtime/src/module.rs | 13 +++++-- crates/wasmtime/src/module/serialization.rs | 1 + src/obj.rs | 1 + 8 files changed, 81 insertions(+), 30 deletions(-) diff --git a/crates/cache/src/lib.rs b/crates/cache/src/lib.rs index f29dd21056..874e481934 100644 --- a/crates/cache/src/lib.rs +++ b/crates/cache/src/lib.rs @@ -43,6 +43,8 @@ impl<'config> ModuleCacheEntry<'config> { } /// Gets cached data if state matches, otherwise calls the `compute`. + // NOTE: This takes a function pointer instead of a closure so that it doesn't accidentally + // close over something not accounted in the cache. pub fn get_data(&self, state: T, compute: fn(T) -> Result) -> Result where T: Hash, diff --git a/crates/jit/src/compiler.rs b/crates/jit/src/compiler.rs index 6d2fc7caf2..cd14dddd30 100644 --- a/crates/jit/src/compiler.rs +++ b/crates/jit/src/compiler.rs @@ -46,6 +46,7 @@ pub struct Compiler { strategy: CompilationStrategy, tunables: Tunables, features: WasmFeatures, + parallel_compilation: bool, } impl Compiler { @@ -55,6 +56,7 @@ impl Compiler { strategy: CompilationStrategy, tunables: Tunables, features: WasmFeatures, + parallel_compilation: bool, ) -> Self { Self { isa, @@ -68,6 +70,7 @@ impl Compiler { }, tunables, features, + parallel_compilation, } } } @@ -137,8 +140,9 @@ impl Compiler { ) -> Result { let functions = mem::take(&mut translation.function_body_inputs); let functions = functions.into_iter().collect::>(); - let funcs = maybe_parallel!(functions.(into_iter | into_par_iter)) - .map(|(index, func)| { + + let funcs = self + .run_maybe_parallel(functions, |(index, func)| { self.compiler.compile_function( translation, index, @@ -147,8 +151,7 @@ impl Compiler { &self.tunables, types, ) - }) - .collect::, _>>()? + })? .into_iter() .collect::(); @@ -172,6 +175,33 @@ impl Compiler { funcs, }) } + + /// Run the given closure in parallel if the compiler is configured to do so. + pub(crate) fn run_maybe_parallel< + A: Send, + B: Send, + E: Send, + F: Fn(A) -> Result + Send + Sync, + >( + &self, + input: Vec, + f: F, + ) -> Result, E> { + if self.parallel_compilation { + #[cfg(feature = "parallel-compilation")] + return input + .into_par_iter() + .map(|a| f(a)) + .collect::, E>>(); + } + + // In case the parallel-compilation feature is disabled or the parallel_compilation config + // was turned off dynamically fallback to the non-parallel version. + input + .into_iter() + .map(|a| f(a)) + .collect::, E>>() + } } impl Hash for Compiler { @@ -182,6 +212,7 @@ impl Hash for Compiler { isa, tunables, features, + parallel_compilation: _, } = self; // Hash compiler's flags: compilation strategy, isa, frontend config, diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index 70894bdfeb..ca90d0ac29 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -8,8 +8,6 @@ use crate::compiler::{Compilation, Compiler}; use crate::link::link_module; use crate::object::ObjectUnwindInfo; use object::File as ObjectFile; -#[cfg(feature = "parallel-compilation")] -use rayon::prelude::*; use serde::{Deserialize, Serialize}; use std::ops::Range; use std::sync::Arc; @@ -112,8 +110,9 @@ impl CompilationArtifacts { .translate(data) .map_err(|error| SetupError::Compile(CompileError::Wasm(error)))?; - let list = maybe_parallel!(translations.(into_iter | into_par_iter)) - .map(|mut translation| { + let list = compiler.run_maybe_parallel::<_, _, SetupError, _>( + translations, + |mut translation| { let Compilation { obj, unwind_info, @@ -159,8 +158,9 @@ impl CompilationArtifacts { }, has_unparsed_debuginfo, }) - }) - .collect::, SetupError>>()?; + }, + )?; + Ok(( main_module, list, @@ -226,10 +226,11 @@ impl CompiledModule { artifacts: Vec, isa: &dyn TargetIsa, profiler: &dyn ProfilingAgent, + compiler: &Compiler, ) -> Result>, SetupError> { - maybe_parallel!(artifacts.(into_iter | into_par_iter)) - .map(|a| CompiledModule::from_artifacts(a, isa, profiler)) - .collect() + compiler.run_maybe_parallel(artifacts, |a| { + CompiledModule::from_artifacts(a, isa, profiler) + }) } /// Creates `CompiledModule` directly from `CompilationArtifacts`. diff --git a/crates/jit/src/lib.rs b/crates/jit/src/lib.rs index 12329ea266..9a21a61f7f 100644 --- a/crates/jit/src/lib.rs +++ b/crates/jit/src/lib.rs @@ -20,20 +20,6 @@ ) )] -#[cfg(feature = "parallel-compilation")] -macro_rules! maybe_parallel { - ($e:ident.($serial:ident | $parallel:ident)) => { - $e.$parallel() - }; -} - -#[cfg(not(feature = "parallel-compilation"))] -macro_rules! maybe_parallel { - ($e:ident.($serial:ident | $parallel:ident)) => { - $e.$serial() - }; -} - mod code_memory; mod compiler; mod instantiate; diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs index df57b82e1f..212121311e 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs @@ -356,6 +356,7 @@ pub struct Config { pub(crate) async_stack_size: usize, pub(crate) async_support: bool, pub(crate) deserialize_check_wasmtime_version: bool, + pub(crate) parallel_compilation: bool, } impl Config { @@ -392,6 +393,7 @@ impl Config { async_stack_size: 2 << 20, async_support: false, deserialize_check_wasmtime_version: true, + parallel_compilation: true, }; ret.cranelift_debug_verifier(false); ret.cranelift_opt_level(OptLevel::Speed); @@ -1210,6 +1212,18 @@ impl Config { self } + /// Configure wether wasmtime should compile a module using multiple threads. + /// + /// Disabling this will result in a single thread being used to compile the wasm bytecode. + /// + /// By default parallel compilation is enabled. + #[cfg(feature = "parallel-compilation")] + #[cfg_attr(nightlydoc, doc(cfg(feature = "parallel-compilation")))] + pub fn parallel_compilation(&mut self, parallel: bool) -> &mut Self { + self.parallel_compilation = parallel; + self + } + pub(crate) fn target_isa(&self) -> Box { self.isa_flags .clone() @@ -1226,7 +1240,13 @@ impl Config { let isa = self.target_isa(); let mut tunables = self.tunables.clone(); allocator.adjust_tunables(&mut tunables); - Compiler::new(isa, self.strategy, tunables, self.features) + Compiler::new( + isa, + self.strategy, + tunables, + self.features, + self.parallel_compilation, + ) } pub(crate) fn build_allocator(&self) -> Result> { diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 2a9168f8f8..d6b3b6a7ba 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -300,11 +300,19 @@ impl Module { engine.cache_config(), ) .get_data((engine.compiler(), binary), |(compiler, binary)| { - CompilationArtifacts::build(compiler, binary, USE_PAGED_MEM_INIT) + CompilationArtifacts::build( + compiler, + binary, + USE_PAGED_MEM_INIT, + ) })?; } else { let (main_module, artifacts, types) = - CompilationArtifacts::build(engine.compiler(), binary, USE_PAGED_MEM_INIT)?; + CompilationArtifacts::build( + engine.compiler(), + binary, + USE_PAGED_MEM_INIT, + )?; } }; @@ -312,6 +320,7 @@ impl Module { artifacts, engine.compiler().isa(), &*engine.config().profiler, + engine.compiler(), )?; Self::from_parts(engine, modules, main_module, Arc::new(types), &[]) diff --git a/crates/wasmtime/src/module/serialization.rs b/crates/wasmtime/src/module/serialization.rs index 8dedf6803f..2918d7ffc6 100644 --- a/crates/wasmtime/src/module/serialization.rs +++ b/crates/wasmtime/src/module/serialization.rs @@ -291,6 +291,7 @@ impl<'a> SerializedModule<'a> { .collect(), engine.compiler().isa(), &*engine.config().profiler, + engine.compiler(), )?; assert!(!modules.is_empty()); diff --git a/src/obj.rs b/src/obj.rs index 529d1c3c6d..d691842613 100644 --- a/src/obj.rs +++ b/src/obj.rs @@ -62,6 +62,7 @@ pub fn compile_to_obj( }, tunables.clone(), features.clone(), + true, // enable parallel compilation ); let environ = ModuleEnvironment::new(compiler.isa().frontend_config(), &tunables, &features);