Cache worker tests

This commit is contained in:
Artur Jamro
2019-09-17 16:38:21 -07:00
committed by Dan Gohman
parent 134bf467e7
commit 512b1196fd
8 changed files with 1039 additions and 131 deletions

View File

@@ -15,12 +15,13 @@ use std::io::Write;
use std::path::{Path, PathBuf};
use std::string::{String, ToString};
#[macro_use] // for tests
mod config;
mod worker;
use config::{cache_config, CacheConfig};
pub use config::{create_new_config, init};
use worker::worker;
use worker::{worker, Worker};
lazy_static! {
static ref SELF_MTIME: String = {
@@ -48,9 +49,12 @@ lazy_static! {
};
}
pub struct ModuleCacheEntry<'config> {
mod_cache_path: Option<PathBuf>,
pub struct ModuleCacheEntry<'config, 'worker>(Option<ModuleCacheEntryInner<'config, 'worker>>);
struct ModuleCacheEntryInner<'config, 'worker> {
mod_cache_path: PathBuf,
cache_config: &'config CacheConfig,
worker: &'worker Worker,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
@@ -72,7 +76,7 @@ type ModuleCacheDataTupleType = (
struct Sha256Hasher(Sha256);
impl<'config> ModuleCacheEntry<'config> {
impl<'config, 'worker> ModuleCacheEntry<'config, 'worker> {
pub fn new<'data>(
module: &Module,
function_body_inputs: &PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
@@ -80,87 +84,104 @@ impl<'config> ModuleCacheEntry<'config> {
compiler_name: &str,
generate_debug_info: bool,
) -> Self {
Self::new_with_config(
module,
function_body_inputs,
isa,
compiler_name,
generate_debug_info,
cache_config(),
)
let cache_config = cache_config();
if cache_config.enabled() {
Self(Some(ModuleCacheEntryInner::new(
module,
function_body_inputs,
isa,
compiler_name,
generate_debug_info,
cache_config,
worker(),
)))
} else {
Self(None)
}
}
fn new_with_config<'data>(
#[cfg(test)]
fn from_inner<'data>(inner: ModuleCacheEntryInner<'config, 'worker>) -> Self {
Self(Some(inner))
}
pub fn get_data(&self) -> Option<ModuleCacheData> {
if let Some(inner) = &self.0 {
inner.get_data().map(|val| {
inner.worker.on_cache_get_async(&inner.mod_cache_path); // call on success
val
})
} else {
None
}
}
pub fn update_data(&self, data: &ModuleCacheData) {
if let Some(inner) = &self.0 {
inner.update_data(data).map(|val| {
inner.worker.on_cache_update_async(&inner.mod_cache_path); // call on success
val
});
}
}
}
impl<'config, 'worker> ModuleCacheEntryInner<'config, 'worker> {
fn new<'data>(
module: &Module,
function_body_inputs: &PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
isa: &dyn isa::TargetIsa,
compiler_name: &str,
generate_debug_info: bool,
cache_config: &'config CacheConfig,
worker: &'worker Worker,
) -> Self {
let mod_cache_path = if cache_config.enabled() {
let hash = Sha256Hasher::digest(module, function_body_inputs);
let compiler_dir = if cfg!(debug_assertions) {
format!(
"{comp_name}-{comp_ver}-{comp_mtime}",
comp_name = compiler_name,
comp_ver = env!("GIT_REV"),
comp_mtime = *SELF_MTIME,
)
} else {
format!(
"{comp_name}-{comp_ver}",
comp_name = compiler_name,
comp_ver = env!("GIT_REV"),
)
};
let mod_filename = format!(
"mod-{mod_hash}{mod_dbg}",
mod_hash = base64::encode_config(&hash, base64::URL_SAFE_NO_PAD), // standard encoding uses '/' which can't be used for filename
mod_dbg = if generate_debug_info { ".d" } else { "" },
);
Some(
cache_config
.directory()
.join(isa.triple().to_string())
.join(compiler_dir)
.join(mod_filename),
let hash = Sha256Hasher::digest(module, function_body_inputs);
let compiler_dir = if cfg!(debug_assertions) {
format!(
"{comp_name}-{comp_ver}-{comp_mtime}",
comp_name = compiler_name,
comp_ver = env!("GIT_REV"),
comp_mtime = *SELF_MTIME,
)
} else {
None
format!(
"{comp_name}-{comp_ver}",
comp_name = compiler_name,
comp_ver = env!("GIT_REV"),
)
};
let mod_filename = format!(
"mod-{mod_hash}{mod_dbg}",
mod_hash = base64::encode_config(&hash, base64::URL_SAFE_NO_PAD), // standard encoding uses '/' which can't be used for filename
mod_dbg = if generate_debug_info { ".d" } else { "" },
);
let mod_cache_path = cache_config
.directory()
.join(isa.triple().to_string())
.join(compiler_dir)
.join(mod_filename);
Self {
mod_cache_path,
cache_config,
worker,
}
}
pub fn get_data(&self) -> Option<ModuleCacheData> {
let path = self.mod_cache_path.as_ref()?;
trace!("get_data() for path: {}", path.display());
let compressed_cache_bytes = fs::read(path).ok()?;
fn get_data(&self) -> Option<ModuleCacheData> {
trace!("get_data() for path: {}", self.mod_cache_path.display());
let compressed_cache_bytes = fs::read(&self.mod_cache_path).ok()?;
let cache_bytes = zstd::decode_all(&compressed_cache_bytes[..])
.map_err(|err| warn!("Failed to decompress cached code: {}", err))
.ok()?;
let ret = bincode::deserialize(&cache_bytes[..])
bincode::deserialize(&cache_bytes[..])
.map_err(|err| warn!("Failed to deserialize cached code: {}", err))
.ok()?;
worker().on_cache_get_async(path); // call on success
Some(ret)
.ok()
}
pub fn update_data(&self, data: &ModuleCacheData) {
if self.update_data_impl(data).is_some() {
let path = self.mod_cache_path.as_ref().unwrap();
worker().on_cache_update_async(path); // call on success
}
}
fn update_data_impl(&self, data: &ModuleCacheData) -> Option<()> {
let path = self.mod_cache_path.as_ref()?;
trace!("update_data() for path: {}", path.display());
fn update_data(&self, data: &ModuleCacheData) -> Option<()> {
trace!("update_data() for path: {}", self.mod_cache_path.display());
let serialized_data = bincode::serialize(&data)
.map_err(|err| warn!("Failed to serialize cached code: {}", err))
.ok()?;
@@ -173,17 +194,17 @@ impl<'config> ModuleCacheEntry<'config> {
// Optimize syscalls: first, try writing to disk. It should succeed in most cases.
// Otherwise, try creating the cache directory and retry writing to the file.
if fs_write_atomic(path, "mod", &compressed_data) {
if fs_write_atomic(&self.mod_cache_path, "mod", &compressed_data) {
return Some(());
}
debug!(
"Attempting to create the cache directory, because \
failed to write cached code to disk, path: {}",
path.display(),
self.mod_cache_path.display(),
);
let cache_dir = path.parent().unwrap();
let cache_dir = self.mod_cache_path.parent().unwrap();
fs::create_dir_all(cache_dir)
.map_err(|err| {
warn!(
@@ -194,7 +215,7 @@ impl<'config> ModuleCacheEntry<'config> {
})
.ok()?;
if fs_write_atomic(path, "mod", &compressed_data) {
if fs_write_atomic(&self.mod_cache_path, "mod", &compressed_data) {
Some(())
} else {
None