Merge pull request 'wasmtime module caching' (#46) from cache-modules into main
Reviewed-on: #46
This commit is contained in:
commit
7ab55cf13b
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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 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)?;
|
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")?;
|
||||||
|
|
Loading…
Reference in New Issue