Merge pull request 'wasmtime module caching' (#46) from cache-modules into main

Reviewed-on: #46
This commit is contained in:
mars 2022-11-26 00:54:25 +00:00
commit 7ab55cf13b
2 changed files with 30 additions and 4 deletions

View File

@ -22,6 +22,7 @@ canary-script = { path = "crates/script" }
lyon = "1" lyon = "1"
ouroboros = "^0.15" ouroboros = "^0.15"
parking_lot = "0.12" parking_lot = "0.12"
prehash = "0.3.3"
slab = "0.4" slab = "0.4"
wasmtime = "0.38" wasmtime = "0.38"

View File

@ -1,6 +1,8 @@
// Copyright (c) 2022 Marceline Cramer // Copyright (c) 2022 Marceline Cramer
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
use std::collections::{hash_map::DefaultHasher, HashMap};
use std::hash::Hasher;
use std::ops::DerefMut; use std::ops::DerefMut;
use super::{Arc, Backend, Instance, PanelId, ScriptAbi}; use super::{Arc, Backend, Instance, PanelId, ScriptAbi};
@ -8,34 +10,57 @@ use crate::DrawCommand;
use canary_script::{Color, CursorEventKind, Rect, Vec2}; use canary_script::{Color, CursorEventKind, Rect, Vec2};
use parking_lot::Mutex; use parking_lot::Mutex;
use prehash::{DefaultPrehasher, Prehashed, Prehasher};
type Caller<'a> = wasmtime::Caller<'a, Arc<ScriptAbi>>; type Caller<'a> = wasmtime::Caller<'a, Arc<ScriptAbi>>;
type Store = wasmtime::Store<Arc<ScriptAbi>>; type Store = wasmtime::Store<Arc<ScriptAbi>>;
type Linker = wasmtime::Linker<Arc<ScriptAbi>>; type Linker = wasmtime::Linker<Arc<ScriptAbi>>;
type ModuleCache = Mutex<HashMap<Prehashed<u64>, wasmtime::Module, DefaultPrehasher>>;
pub struct WasmtimeBackend { pub struct WasmtimeBackend {
engine: wasmtime::Engine, engine: wasmtime::Engine,
module_cache: ModuleCache,
} }
impl WasmtimeBackend { impl WasmtimeBackend {
pub fn new() -> anyhow::Result<Self> { pub fn new() -> anyhow::Result<Self> {
let mut config = wasmtime::Config::new(); let mut config = wasmtime::Config::new();
config.wasm_simd(true); config.wasm_simd(true);
config.wasm_bulk_memory(true); config.wasm_bulk_memory(true);
config.cranelift_opt_level(wasmtime::OptLevel::Speed); config.cranelift_opt_level(wasmtime::OptLevel::Speed);
config.cache_config_load_default()?;
let engine = wasmtime::Engine::new(&config)?; let engine = wasmtime::Engine::new(&config)?;
let module_cache = Default::default();
Ok(Self { engine }) Ok(Self {
engine,
module_cache,
})
} }
} }
impl Backend for WasmtimeBackend { impl Backend for WasmtimeBackend {
fn load_module(&self, abi: Arc<ScriptAbi>, module: &[u8]) -> anyhow::Result<Arc<dyn Instance>> { fn load_module(&self, abi: Arc<ScriptAbi>, module: &[u8]) -> anyhow::Result<Arc<dyn Instance>> {
let module = wasmtime::Module::new(&self.engine, module)?; let mut hasher = DefaultHasher::new();
hasher.write(module);
let hashed = hasher.finish();
let prehasher = DefaultPrehasher::new();
let prehashed = prehasher.prehash(hashed);
let mut cache = self.module_cache.lock();
let module = if let Some(module) = cache.get(&prehashed) {
module
} else {
let module = wasmtime::Module::new(&self.engine, module)?;
cache.insert(prehashed, module);
cache.get(&prehashed).unwrap()
};
let mut store = wasmtime::Store::new(&self.engine, abi); let mut store = wasmtime::Store::new(&self.engine, abi);
let mut linker = Linker::new(&self.engine); let mut linker = Linker::new(&self.engine);
WasmtimeInstance::link(&mut linker)?; WasmtimeInstance::link(&mut linker)?;
let instance = linker.instantiate(&mut store, &module)?; let instance = linker.instantiate(&mut store, module)?;
let bind_panel = instance.get_typed_func(&mut store, "bind_panel")?; let bind_panel = instance.get_typed_func(&mut store, "bind_panel")?;
let update = instance.get_typed_func(&mut store, "update")?; let update = instance.get_typed_func(&mut store, "update")?;
let draw = instance.get_typed_func(&mut store, "draw")?; let draw = instance.get_typed_func(&mut store, "draw")?;