Skip to content

Commit

Permalink
Re-work deserializing to not rely on Artifact::is_deserializable()
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael-F-Bryan committed Jun 26, 2023
1 parent f15780e commit 4223625
Showing 1 changed file with 27 additions and 49 deletions.
76 changes: 27 additions & 49 deletions lib/wasix/src/runtime/module_cache/filesystem.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::{
fs::File,
io::{BufReader, BufWriter, Read, Seek, Write},
io::{BufWriter, Write},
path::{Path, PathBuf},
};

Expand Down Expand Up @@ -47,10 +46,9 @@ impl ModuleCache for FileSystemCache {
// background.
// https://github.com/wasmerio/wasmer/issues/3851

let uncompressed = read_compressed(&path)?;
let bytes = read_file(&path)?;

let res = unsafe { Module::deserialize(&engine, uncompressed) };
match res {
match deserialize(&bytes, engine) {
Ok(m) => {
tracing::debug!("Cache hit!");
Ok(m)
Expand All @@ -72,7 +70,7 @@ impl ModuleCache for FileSystemCache {
);
}

Err(CacheError::Deserialize(e))
Err(e)
}
}
}
Expand Down Expand Up @@ -118,21 +116,18 @@ impl ModuleCache for FileSystemCache {
}
}

/// Read a file that may or may not be compressed.
fn read_compressed(path: &Path) -> Result<Vec<u8>, CacheError> {
let mut f = match File::open(path) {
Ok(f) => BufReader::new(f),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
return Err(CacheError::NotFound);
}
Err(error) => {
return Err(CacheError::FileRead {
path: path.to_path_buf(),
error,
});
}
};
fn read_file(path: &Path) -> Result<Vec<u8>, CacheError> {
match std::fs::read(path) {
Ok(bytes) => Ok(bytes),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Err(CacheError::NotFound),
Err(error) => Err(CacheError::FileRead {
path: path.to_path_buf(),
error,
}),
}
}

fn deserialize(bytes: &[u8], engine: &Engine) -> Result<Module, CacheError> {
// We used to compress our compiled modules using LZW encoding in the past.
// This was removed because it has a negative impact on startup times for
// "wasmer run", so all new compiled modules should be saved directly to
Expand All @@ -148,37 +143,20 @@ fn read_compressed(path: &Path) -> Result<Vec<u8>, CacheError> {
// - ModuleCache::save(): 2.4s, 72MB binary
// - ModuleCache::load(): 822ms

let mut leading_bytes = [0_u8; 128];
f.read_exact(&mut leading_bytes)
.and_then(|_| f.rewind())
.map_err(|error| CacheError::FileRead {
path: path.to_path_buf(),
error,
})?;

if wasmer::Artifact::is_deserializable(&leading_bytes) {
// the compiled artifact was saved as-is. Return it.
let mut artifact = Vec::new();
f.read_to_end(&mut artifact)
.map_err(|error| CacheError::FileRead {
path: path.to_path_buf(),
error,
})?;

return Ok(artifact);
}
match unsafe { Module::deserialize(engine, bytes) } {
// The happy case
Ok(m) => Ok(m),
Err(wasmer::DeserializeError::Incompatible(_)) => {
let bytes = weezl::decode::Decoder::new(weezl::BitOrder::Msb, 8)
.decode(bytes)
.map_err(CacheError::other)?;

// Fall back to LZW decoding
let m = unsafe { Module::deserialize(engine, bytes)? };

let mut uncompressed = Vec::new();
let mut decoder = weezl::decode::Decoder::new(weezl::BitOrder::Msb, 8);
decoder
.into_stream(&mut uncompressed)
.decode_all(f)
.status
.map_err(CacheError::other)?;

Ok(uncompressed)
Ok(m)
}
Err(e) => Err(CacheError::Deserialize(e)),
}
}

#[cfg(test)]
Expand Down

0 comments on commit 4223625

Please sign in to comment.