diff --git a/Cargo.toml b/Cargo.toml index fe2e0dd..55b8413 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ ouroboros = "^0.15" parking_lot = "0.12" slab = "0.4" wasmtime = "0.38" +prehash = "0.3.3" [dependencies.font-kit] version = "*" diff --git a/src/backend/wasmtime.rs b/src/backend/wasmtime.rs index 7df636a..22aaacd 100644 --- a/src/backend/wasmtime.rs +++ b/src/backend/wasmtime.rs @@ -1,4 +1,10 @@ -use std::ops::DerefMut; +use std::collections::hash_map::RandomState; +use std::hash::{Hash, BuildHasher}; +use std::{ops::DerefMut, collections::hash_map}; +use std::collections::HashMap; + +use std::collections::hash_map::DefaultHasher; +use std::hash::Hasher; use super::{Arc, Backend, Instance, PanelId}; use crate::{DrawCommand, ScriptAbi, ScriptAbiImpl}; @@ -9,9 +15,14 @@ use parking_lot::Mutex; type Caller<'a> = wasmtime::Caller<'a, ScriptAbiImpl>; type Store = wasmtime::Store; type Linker = wasmtime::Linker; +type ModuleCache = Mutex, wasmtime::Module, DefaultPrehasher>>; + +use prehash::{new_prehashed_set, DefaultPrehasher, Prehasher, Prehashed}; +use wasmtime::Module; pub struct WasmtimeBackend { engine: wasmtime::Engine, + module_cache: ModuleCache, } impl WasmtimeBackend { @@ -23,21 +34,35 @@ impl WasmtimeBackend { config.cache_config_load_default()?; let engine = wasmtime::Engine::new(&config)?; - - Ok(Self { engine }) + let module_cache = Default::default(); + Ok(Self { engine, module_cache }) } } - impl Backend for WasmtimeBackend { - fn load_module(&self, module: &[u8]) -> anyhow::Result> { - 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 gotten = 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 abi = ScriptAbiImpl::default(); let mut store = wasmtime::Store::new(&self.engine, abi); let mut linker = Linker::new(&self.engine); WasmtimeInstance::link(&mut linker)?; - let instance = linker.instantiate(&mut store, &module)?; + let instance = linker.instantiate(&mut store, gotten)?; let bind_panel = instance.get_typed_func(&mut store, "bind_panel")?; let update = instance.get_typed_func(&mut store, "update")?; let draw = instance.get_typed_func(&mut store, "draw")?;