Skip to content

Commit

Permalink
wasmtime: Option to disable parallel compilation (#3169)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
pepyakin authored Aug 10, 2021
1 parent 42acb72 commit cbabcac
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 30 deletions.
2 changes: 2 additions & 0 deletions crates/cache/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T, U, E>(&self, state: T, compute: fn(T) -> Result<U, E>) -> Result<U, E>
where
T: Hash,
Expand Down
39 changes: 35 additions & 4 deletions crates/jit/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub struct Compiler {
strategy: CompilationStrategy,
tunables: Tunables,
features: WasmFeatures,
parallel_compilation: bool,
}

impl Compiler {
Expand All @@ -55,6 +56,7 @@ impl Compiler {
strategy: CompilationStrategy,
tunables: Tunables,
features: WasmFeatures,
parallel_compilation: bool,
) -> Self {
Self {
isa,
Expand All @@ -68,6 +70,7 @@ impl Compiler {
},
tunables,
features,
parallel_compilation,
}
}
}
Expand Down Expand Up @@ -137,8 +140,9 @@ impl Compiler {
) -> Result<Compilation, SetupError> {
let functions = mem::take(&mut translation.function_body_inputs);
let functions = functions.into_iter().collect::<Vec<_>>();
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,
Expand All @@ -147,8 +151,7 @@ impl Compiler {
&self.tunables,
types,
)
})
.collect::<Result<Vec<_>, _>>()?
})?
.into_iter()
.collect::<CompiledFunctions>();

Expand All @@ -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<B, E> + Send + Sync,
>(
&self,
input: Vec<A>,
f: F,
) -> Result<Vec<B>, E> {
if self.parallel_compilation {
#[cfg(feature = "parallel-compilation")]
return input
.into_par_iter()
.map(|a| f(a))
.collect::<Result<Vec<B>, 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::<Result<Vec<B>, E>>()
}
}

impl Hash for Compiler {
Expand All @@ -182,6 +212,7 @@ impl Hash for Compiler {
isa,
tunables,
features,
parallel_compilation: _,
} = self;

// Hash compiler's flags: compilation strategy, isa, frontend config,
Expand Down
19 changes: 10 additions & 9 deletions crates/jit/src/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -159,8 +158,9 @@ impl CompilationArtifacts {
},
has_unparsed_debuginfo,
})
})
.collect::<Result<Vec<_>, SetupError>>()?;
},
)?;

Ok((
main_module,
list,
Expand Down Expand Up @@ -226,10 +226,11 @@ impl CompiledModule {
artifacts: Vec<CompilationArtifacts>,
isa: &dyn TargetIsa,
profiler: &dyn ProfilingAgent,
compiler: &Compiler,
) -> Result<Vec<Arc<Self>>, 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`.
Expand Down
14 changes: 0 additions & 14 deletions crates/jit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
22 changes: 21 additions & 1 deletion crates/wasmtime/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<dyn TargetIsa> {
self.isa_flags
.clone()
Expand All @@ -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<Box<dyn InstanceAllocator>> {
Expand Down
13 changes: 11 additions & 2 deletions crates/wasmtime/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,18 +300,27 @@ 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,
)?;
}
};

let modules = CompiledModule::from_artifacts_list(
artifacts,
engine.compiler().isa(),
&*engine.config().profiler,
engine.compiler(),
)?;

Self::from_parts(engine, modules, main_module, Arc::new(types), &[])
Expand Down
1 change: 1 addition & 0 deletions crates/wasmtime/src/module/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ impl<'a> SerializedModule<'a> {
.collect(),
engine.compiler().isa(),
&*engine.config().profiler,
engine.compiler(),
)?;

assert!(!modules.is_empty());
Expand Down
1 change: 1 addition & 0 deletions src/obj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit cbabcac

Please sign in to comment.