Skip to content

Commit

Permalink
Merge pull request #101 from holochain/2023-11-08-persist
Browse files Browse the repository at this point in the history
2023 11 08 persist
  • Loading branch information
thedavidmeister authored Nov 13, 2023
2 parents 94f6853 + 5cf94e4 commit 3552723
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 14 deletions.
1 change: 1 addition & 0 deletions crates/host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ parking_lot = "0.12"
rand = "0.8"
bimap = "0.6"
bytes = "1"
hex = "0.4"

[lib]
name = "holochain_wasmer_host"
Expand Down
58 changes: 48 additions & 10 deletions crates/host/src/module.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use crate::plru::MicroCache;
use crate::prelude::*;
use bimap::BiMap;
use bytes::BufMut;
use bytes::Bytes;
use bytes::BytesMut;
use holochain_wasmer_common::WasmError;
use parking_lot::Mutex;
use std::collections::BTreeMap;
use std::fs::File;
use std::path::PathBuf;
use std::sync::Arc;
use wasmer::Cranelift;
use wasmer::Instance;
Expand Down Expand Up @@ -115,10 +119,11 @@ pub trait PlruCache {
/// be deserialized before it can be used to build instances. The deserialization
/// process is far faster than compiling and much slower than instance building.
pub struct SerializedModuleCache {
plru: MicroCache,
key_map: PlruKeyMap,
cache: BTreeMap<CacheKey, Arc<SerializedModule>>,
cranelift: fn() -> Cranelift,
pub plru: MicroCache,
pub key_map: PlruKeyMap,
pub cache: BTreeMap<CacheKey, Arc<SerializedModule>>,
pub cranelift: fn() -> Cranelift,
pub maybe_fs_dir: Option<PathBuf>,
}

impl PlruCache for SerializedModuleCache {
Expand Down Expand Up @@ -154,9 +159,16 @@ impl SerializedModuleCache {
plru: MicroCache::default(),
key_map: PlruKeyMap::default(),
cache: BTreeMap::default(),
maybe_fs_dir: None,
}
}

fn module_path(&self, key: CacheKey) -> Option<PathBuf> {
self.maybe_fs_dir
.as_ref()
.map(|dir_path| dir_path.clone().join(hex::encode(key)))
}

/// Given a wasm, compiles with cranelift, serializes the result, adds it to
/// the cache and returns that.
fn get_with_build_cache(
Expand All @@ -165,12 +177,38 @@ impl SerializedModuleCache {
wasm: &[u8],
) -> Result<Arc<ModuleWithStore>, wasmer::RuntimeError> {
let store = Store::new((self.cranelift)());
let module = Module::from_binary(&store, wasm)
.map_err(|e| wasm_error!(WasmErrorInner::Compile(e.to_string())))?;
let serialized_module = module
.serialize()
.map_err(|e| wasm_error!(WasmErrorInner::Compile(e.to_string())))?;
self.put_item(key, Arc::new(serialized_module));

let maybe_module_path = self.module_path(key);
let (module, serialized_module) = match maybe_module_path.as_ref().map(|module_path| {
// We do this the long way to get `Bytes` instead of `Vec<u8>` so
// that the clone when we both deserialize and cache is cheap.
let mut file = File::open(module_path)
.map_err(|e| wasm_error!(WasmErrorInner::Compile(e.to_string())))?;
let mut bytes_mut = BytesMut::new().writer();
std::io::copy(&mut file, &mut bytes_mut)
.map_err(|e| wasm_error!(WasmErrorInner::Compile(e.to_string())))?;
Ok::<bytes::Bytes, wasmer::RuntimeError>(bytes_mut.into_inner().freeze())
}) {
Some(Ok(serialized_module)) => (
unsafe { Module::deserialize(&store, serialized_module.clone()) }
.map_err(|e| wasm_error!(WasmErrorInner::Compile(e.to_string())))?,
serialized_module,
),
_fs_miss => {
let module = Module::from_binary(&store, wasm)
.map_err(|e| wasm_error!(WasmErrorInner::Compile(e.to_string())))?;
let serialized_module = module
.serialize()
.map_err(|e| wasm_error!(WasmErrorInner::Compile(e.to_string())))?;
if let Some(module_path) = maybe_module_path {
std::fs::write(module_path, &serialized_module)
.map_err(|e| wasm_error!(WasmErrorInner::Compile(e.to_string())))?;
}
(module, serialized_module)
}
};
self.put_item(key, Arc::new(serialized_module.clone()));

Ok(Arc::new(ModuleWithStore {
store: Arc::new(Mutex::new(store)),
module: Arc::new(module),
Expand Down
73 changes: 69 additions & 4 deletions test/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ wasmer = "=4.2.2"
wasmer-middlewares = "=4.2.2"
test-fuzz = "=3.0.4"
once_cell = "1"
tempfile = "3"

[dev-dependencies]
env_logger = "0.8"
Expand Down
48 changes: 48 additions & 0 deletions test/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,54 @@ use criterion::Throughput;
use criterion::{criterion_group, criterion_main, Criterion};
use holochain_wasmer_host::prelude::*;
use rand::prelude::*;
use tempfile::TempDir;
use test::wasms::TestWasm;
use wasmer::AsStoreMut;
use wasmer::Module;
use wasmer::Store;

/// compile a module
pub fn wasm_module_compile(c: &mut Criterion) {
let mut group = c.benchmark_group("wasm_module_compile");

for wasm in vec![
TestWasm::Empty,
TestWasm::Io,
TestWasm::Test,
TestWasm::Memory,
] {
group.bench_function(BenchmarkId::new("wasm_module_compile", wasm.name()), |b| {
b.iter(|| {
Module::from_binary(&Store::default(), wasm.bytes()).unwrap();
})
});
}
}

/// deserialize a module from a file
pub fn wasm_module_deserialize_from_file(c: &mut Criterion) {
let mut group = c.benchmark_group("wasm_module_deserialize_from_file");

for wasm in vec![
TestWasm::Empty,
TestWasm::Io,
TestWasm::Test,
TestWasm::Memory,
] {
let tmpdir = TempDir::new().unwrap();
let path = tmpdir.path().join(wasm.name());
let module = Module::from_binary(&Store::default(), wasm.bytes()).unwrap();
module.serialize_to_file(&path).unwrap();
group.bench_function(
BenchmarkId::new("wasm_module_deserialize_from_file", wasm.name()),
|b| {
b.iter(|| unsafe {
Module::deserialize_from_file(&Store::default(), &path).unwrap();
})
},
);
}
}

/// create a module
pub fn wasm_module(c: &mut Criterion) {
Expand Down Expand Up @@ -228,6 +274,8 @@ pub fn test_instances(c: &mut Criterion) {

criterion_group!(
benches,
wasm_module_compile,
wasm_module_deserialize_from_file,
wasm_module,
wasm_instance,
wasm_call,
Expand Down

0 comments on commit 3552723

Please sign in to comment.