WasmExecutor takes a cache directory (#8057)

That is useful for executors like wasmtime which produces compiled code
and can actually benefit from caching under some circumstances
This commit is contained in:
Sergei Shulepov
2021-02-09 17:48:29 +01:00
committed by GitHub
parent ef6615ba65
commit eb7226bb4a
6 changed files with 104 additions and 8 deletions
@@ -25,6 +25,7 @@ use crate::state_holder;
use std::rc::Rc;
use std::sync::Arc;
use std::path::Path;
use sc_executor_common::{
error::{Result, WasmError},
wasm_runtime::{WasmModule, WasmInstance, InvokeMethod},
@@ -119,20 +120,68 @@ impl WasmInstance for WasmtimeInstance {
}
}
/// Prepare a directory structure and a config file to enable wasmtime caching.
///
/// In case of an error the caching will not be enabled.
fn setup_wasmtime_caching(
cache_path: &Path,
config: &mut Config,
) -> std::result::Result<(), String> {
use std::fs;
let wasmtime_cache_root = cache_path.join("wasmtime");
fs::create_dir_all(&wasmtime_cache_root)
.map_err(|err| format!("cannot create the dirs to cache: {:?}", err))?;
// Canonicalize the path after creating the directories.
let wasmtime_cache_root = wasmtime_cache_root
.canonicalize()
.map_err(|err| format!("failed to canonicalize the path: {:?}", err))?;
// Write the cache config file
let cache_config_path = wasmtime_cache_root.join("cache-config.toml");
let config_content = format!(
"\
[cache]
enabled = true
directory = \"{cache_dir}\"
",
cache_dir = wasmtime_cache_root.display()
);
fs::write(&cache_config_path, config_content)
.map_err(|err| format!("cannot write the cache config: {:?}", err))?;
config
.cache_config_load(cache_config_path)
.map_err(|err| format!("failed to parse the config: {:?}", err))?;
Ok(())
}
/// Create a new `WasmtimeRuntime` given the code. This function performs translation from Wasm to
/// machine code, which can be computationally heavy.
///
/// The `cache_path` designates where this executor implementation can put compiled artifacts.
pub fn create_runtime(
code: &[u8],
heap_pages: u64,
host_functions: Vec<&'static dyn Function>,
allow_missing_func_imports: bool,
cache_path: Option<&Path>,
) -> std::result::Result<WasmtimeRuntime, WasmError> {
// Create the engine, store and finally the module from the given code.
let mut config = Config::new();
config.cranelift_opt_level(wasmtime::OptLevel::SpeedAndSize);
if let Some(cache_path) = cache_path {
if let Err(reason) = setup_wasmtime_caching(cache_path, &mut config) {
log::warn!(
"failed to setup wasmtime cache. Performance may degrade significantly: {}.",
reason,
);
}
}
let engine = Engine::new(&config);
let module_wrapper = ModuleWrapper::new(&engine, code)
.map_err(|e| WasmError::Other(format!("cannot create module: {}", e)))?;