Enable explicitly initializating copy-on-write images (#3964)
This commit adds a method, `Module::initialize_copy_on_write_image`, which will explicitly create the copy-on-write image during the method call instead of lazily deferring it until the first instantiation of a module. Given the relative expense of creation of a memfd on Linux this can otherwise run the risk of unnaturally perturbing the time-of-instantiation of a module. Additionally whenever lazy initialization is provided in an API it's typically good practice to also have an optionally-called forced initialization.
This commit is contained in:
@@ -618,6 +618,12 @@ impl<T> InstancePre<T> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a reference to the module that this [`InstancePre`] will be
|
||||||
|
/// instantiating.
|
||||||
|
pub fn module(&self) -> &Module {
|
||||||
|
&self.module
|
||||||
|
}
|
||||||
|
|
||||||
/// Instantiates this instance, creating a new instance within the provided
|
/// Instantiates this instance, creating a new instance within the provided
|
||||||
/// `store`.
|
/// `store`.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -821,6 +821,38 @@ impl Module {
|
|||||||
pub fn image_range(&self) -> Range<usize> {
|
pub fn image_range(&self) -> Range<usize> {
|
||||||
self.compiled_module().image_range()
|
self.compiled_module().image_range()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Force initialization of copy-on-write images to happen here-and-now
|
||||||
|
/// instead of when they're requested during first instantiation.
|
||||||
|
///
|
||||||
|
/// When [copy-on-write memory
|
||||||
|
/// initialization](crate::Config::memory_init_cow) is enabled then Wasmtime
|
||||||
|
/// will lazily create the initialization image for a module. This method
|
||||||
|
/// can be used to explicitly dictate when this initialization happens.
|
||||||
|
///
|
||||||
|
/// Note that this largely only matters on Linux when memfd is used.
|
||||||
|
/// Otherwise the copy-on-write image typically comes from disk and in that
|
||||||
|
/// situation the creation of the image is trivial as the image is always
|
||||||
|
/// sourced from disk. On Linux, though, when memfd is used a memfd is
|
||||||
|
/// created and the initialization image is written to it.
|
||||||
|
///
|
||||||
|
/// Also note that this method is not required to be called, it's available
|
||||||
|
/// as a performance optimization if required but is otherwise handled
|
||||||
|
/// automatically.
|
||||||
|
pub fn initialize_copy_on_write_image(&self) -> Result<()> {
|
||||||
|
self.inner.memory_images()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModuleInner {
|
||||||
|
fn memory_images(&self) -> Result<Option<&ModuleMemoryImages>> {
|
||||||
|
let images = self
|
||||||
|
.memory_images
|
||||||
|
.get_or_try_init(|| memory_images(&self.engine, &self.module))?
|
||||||
|
.as_ref();
|
||||||
|
Ok(images)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _assert_send_sync() {
|
fn _assert_send_sync() {
|
||||||
@@ -874,12 +906,8 @@ impl wasmtime_runtime::ModuleRuntimeInfo for ModuleInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn memory_image(&self, memory: DefinedMemoryIndex) -> Result<Option<&Arc<MemoryImage>>> {
|
fn memory_image(&self, memory: DefinedMemoryIndex) -> Result<Option<&Arc<MemoryImage>>> {
|
||||||
let images = self
|
let images = self.memory_images()?;
|
||||||
.memory_images
|
Ok(images.and_then(|images| images.get_memory_image(memory)))
|
||||||
.get_or_try_init(|| memory_images(&self.engine, &self.module))?;
|
|
||||||
Ok(images
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|images| images.get_memory_image(memory)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unique_id(&self) -> Option<CompiledModuleId> {
|
fn unique_id(&self) -> Option<CompiledModuleId> {
|
||||||
|
|||||||
Reference in New Issue
Block a user