Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update memfd support with a runtime toggle #3778

Merged
merged 1 commit into from
Feb 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ default = [
"wasmtime/parallel-compilation",
"wasi-nn",
"pooling-allocator",
"memfd",
]
jitdump = ["wasmtime/jitdump"]
vtune = ["wasmtime/vtune"]
Expand Down
4 changes: 3 additions & 1 deletion crates/fuzzing/src/generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub struct WasmtimeConfig {
pub(crate) consume_fuel: bool,
memory_config: MemoryConfig,
force_jump_veneers: bool,
memfd: bool,
}

#[derive(Arbitrary, Clone, Debug, Eq, Hash, PartialEq)]
Expand Down Expand Up @@ -99,7 +100,8 @@ impl Config {
.cranelift_nan_canonicalization(self.wasmtime.canonicalize_nans)
.cranelift_opt_level(self.wasmtime.opt_level.to_wasmtime())
.interruptable(self.wasmtime.interruptable)
.consume_fuel(self.wasmtime.consume_fuel);
.consume_fuel(self.wasmtime.consume_fuel)
.memfd(self.wasmtime.memfd);

// If the wasm-smith-generated module use nan canonicalization then we
// don't need to enable it, but if it doesn't enable it already then we
Expand Down
11 changes: 10 additions & 1 deletion crates/wasmtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,16 @@ wasi-cap-std-sync = { path = "../wasi-common/cap-std-sync" }
maintenance = { status = "actively-developed" }

[features]
default = ['async', 'cache', 'wat', 'jitdump', 'parallel-compilation', 'cranelift', 'pooling-allocator']
default = [
'async',
'cache',
'wat',
'jitdump',
'parallel-compilation',
'cranelift',
'pooling-allocator',
'memfd',
]

# An on-by-default feature enabling runtime compilation of WebAssembly modules
# with the Cranelift compiler. Cranelift is the default compilation backend of
Expand Down
30 changes: 30 additions & 0 deletions crates/wasmtime/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ pub struct Config {
pub(crate) module_version: ModuleVersionStrategy,
pub(crate) parallel_compilation: bool,
pub(crate) paged_memory_initialization: bool,
pub(crate) memfd: bool,
}

impl Config {
Expand All @@ -129,6 +130,7 @@ impl Config {
parallel_compilation: true,
// Default to paged memory initialization when using uffd on linux
paged_memory_initialization: cfg!(all(target_os = "linux", feature = "uffd")),
memfd: false,
};
#[cfg(compiler)]
{
Expand Down Expand Up @@ -1170,6 +1172,33 @@ impl Config {
self
}

/// Configures whether `memfd`, if supported, will be used to initialize
/// applicable module memories.
///
/// This is a Linux-specific feature since `memfd` is only supported on
/// Linux. Support for this is also enabled by default at compile time but
/// is otherwise disabled at runtime by default. This feature needs to be
/// enabled to `true` for support to be used.
///
/// Also note that even if this feature is enabled it may not be applicable
/// to all memories in all wasm modules. At this time memories must meet
/// specific criteria to be memfd-initialized:
///
/// * Only memories defined in the module can be initialized this way.
/// * Data segments for memory must use statically known offsets.
/// * Data segments for memory must all be in-bounds.
///
/// If all of the above applies, this setting is enabled, and the current
/// platform is Linux the `memfd` will be used to efficiently initialize
/// linear memories with `mmap` to avoid copying data from initializers into
/// linear memory.
#[cfg(feature = "memfd")]
#[cfg_attr(nightlydoc, doc(cfg(feature = "memfd")))]
pub fn memfd(&mut self, memfd: bool) -> &mut Self {
self.memfd = memfd;
self
}

pub(crate) fn build_allocator(&self) -> Result<Box<dyn InstanceAllocator>> {
#[cfg(feature = "async")]
let stack_size = self.async_stack_size;
Expand Down Expand Up @@ -1239,6 +1268,7 @@ impl Clone for Config {
module_version: self.module_version.clone(),
parallel_compilation: self.parallel_compilation,
paged_memory_initialization: self.paged_memory_initialization,
memfd: self.memfd,
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions crates/wasmtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,21 @@
//! all architectures for both the JIT compiler and the `wasmtime compile` CLI
//! command.
//!
//! * `pooling-allocator` - Enabled by default, this feature adds support for
//! the pooling allocation strategy enabled via
//! [`Config::allocation_strategy`]. The pooling allocator can enable more
//! efficient reuse of resources for high-concurrency and
//! high-instantiation-count scenarios.
//!
//! * `memfd` - Enabled by default, this feature builds in support for a
//! Linux-specific feature of creating a `memfd` where applicable for a
//! [`Module`]'s initial memory. This makes instantiation much faster by
//! `mmap`-ing the initial memory image into place instead of copying memory
//! into place, allowing sharing pages that end up only getting read and
//! otherwise using copy-on-write for efficient initialization of memory. Note
//! that this is simply compile-time support and this must also be enabled at
//! run-time via [`Config::memfd`].
//!
//! ## Examples
//!
//! In addition to the examples below be sure to check out the [online embedding
Expand Down
3 changes: 3 additions & 0 deletions crates/wasmtime/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,9 @@ impl Module {
}

pub(crate) fn memfds(&self) -> Result<Option<&Arc<ModuleMemFds>>> {
if !self.engine().config().memfd {
return Ok(None);
}
Ok(self
.inner
.memfds
Expand Down