1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-24 15:19:26 -05:00

perf: skip saving to emit cache after first failure (#24896)

This commit is contained in:
David Sherret 2024-08-08 11:41:30 +02:00 committed by GitHub
parent 93d479252b
commit 6fce23c54e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 41 additions and 16 deletions

22
cli/cache/emit.rs vendored
View file

@ -6,6 +6,7 @@ use deno_ast::ModuleSpecifier;
use deno_core::anyhow::anyhow; use deno_core::anyhow::anyhow;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::serde_json; use deno_core::serde_json;
use deno_core::unsync::sync::AtomicFlag;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
@ -19,10 +20,10 @@ struct EmitMetadata {
} }
/// The cache that stores previously emitted files. /// The cache that stores previously emitted files.
#[derive(Clone)]
pub struct EmitCache { pub struct EmitCache {
disk_cache: DiskCache, disk_cache: DiskCache,
cli_version: &'static str, cli_version: &'static str,
emit_failed_flag: AtomicFlag,
} }
impl EmitCache { impl EmitCache {
@ -30,6 +31,7 @@ impl EmitCache {
Self { Self {
disk_cache, disk_cache,
cli_version: crate::version::deno(), cli_version: crate::version::deno(),
emit_failed_flag: Default::default(),
} }
} }
@ -87,12 +89,10 @@ impl EmitCache {
code: &[u8], code: &[u8],
) { ) {
if let Err(err) = self.set_emit_code_result(specifier, source_hash, code) { if let Err(err) = self.set_emit_code_result(specifier, source_hash, code) {
// should never error here, but if it ever does don't fail // might error in cases such as a readonly file system
if cfg!(debug_assertions) { log::debug!("Error saving emit data ({}): {}", specifier, err);
panic!("Error saving emit data ({specifier}): {err}"); // assume the cache can't be written to and disable caching to it
} else { self.emit_failed_flag.raise();
log::debug!("Error saving emit data({}): {}", specifier, err);
}
} }
} }
@ -102,6 +102,11 @@ impl EmitCache {
source_hash: u64, source_hash: u64,
code: &[u8], code: &[u8],
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
if self.emit_failed_flag.is_raised() {
log::debug!("Skipped emit cache save of {}", specifier);
return Ok(());
}
let meta_filename = self let meta_filename = self
.get_meta_filename(specifier) .get_meta_filename(specifier)
.ok_or_else(|| anyhow!("Could not get meta filename."))?; .ok_or_else(|| anyhow!("Could not get meta filename."))?;
@ -161,6 +166,7 @@ mod test {
let cache = EmitCache { let cache = EmitCache {
disk_cache: disk_cache.clone(), disk_cache: disk_cache.clone(),
cli_version: "1.0.0", cli_version: "1.0.0",
emit_failed_flag: Default::default(),
}; };
let to_string = let to_string =
|bytes: Vec<u8>| -> String { String::from_utf8(bytes).unwrap() }; |bytes: Vec<u8>| -> String { String::from_utf8(bytes).unwrap() };
@ -192,6 +198,7 @@ mod test {
let cache = EmitCache { let cache = EmitCache {
disk_cache: disk_cache.clone(), disk_cache: disk_cache.clone(),
cli_version: "2.0.0", cli_version: "2.0.0",
emit_failed_flag: Default::default(),
}; };
assert_eq!(cache.get_emit_code(&specifier1, 10), None); assert_eq!(cache.get_emit_code(&specifier1, 10), None);
cache.set_emit_code(&specifier1, 5, emit_code1.as_bytes()); cache.set_emit_code(&specifier1, 5, emit_code1.as_bytes());
@ -200,6 +207,7 @@ mod test {
let cache = EmitCache { let cache = EmitCache {
disk_cache, disk_cache,
cli_version: "2.0.0", cli_version: "2.0.0",
emit_failed_flag: Default::default(),
}; };
assert_eq!( assert_eq!(
cache.get_emit_code(&specifier1, 5).map(to_string), cache.get_emit_code(&specifier1, 5).map(to_string),

4
cli/cache/mod.rs vendored
View file

@ -106,7 +106,7 @@ pub use deno_cache_dir::HttpCache;
/// A "wrapper" for the FileFetcher and DiskCache for the Deno CLI that provides /// A "wrapper" for the FileFetcher and DiskCache for the Deno CLI that provides
/// a concise interface to the DENO_DIR when building module graphs. /// a concise interface to the DENO_DIR when building module graphs.
pub struct FetchCacher { pub struct FetchCacher {
emit_cache: EmitCache, emit_cache: Arc<EmitCache>,
file_fetcher: Arc<FileFetcher>, file_fetcher: Arc<FileFetcher>,
file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>, file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
global_http_cache: Arc<GlobalHttpCache>, global_http_cache: Arc<GlobalHttpCache>,
@ -118,7 +118,7 @@ pub struct FetchCacher {
impl FetchCacher { impl FetchCacher {
pub fn new( pub fn new(
emit_cache: EmitCache, emit_cache: Arc<EmitCache>,
file_fetcher: Arc<FileFetcher>, file_fetcher: Arc<FileFetcher>,
file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>, file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
global_http_cache: Arc<GlobalHttpCache>, global_http_cache: Arc<GlobalHttpCache>,

View file

@ -18,7 +18,7 @@ use deno_graph::ModuleGraph;
use std::sync::Arc; use std::sync::Arc;
pub struct Emitter { pub struct Emitter {
emit_cache: EmitCache, emit_cache: Arc<EmitCache>,
parsed_source_cache: Arc<ParsedSourceCache>, parsed_source_cache: Arc<ParsedSourceCache>,
transpile_and_emit_options: transpile_and_emit_options:
Arc<(deno_ast::TranspileOptions, deno_ast::EmitOptions)>, Arc<(deno_ast::TranspileOptions, deno_ast::EmitOptions)>,
@ -28,7 +28,7 @@ pub struct Emitter {
impl Emitter { impl Emitter {
pub fn new( pub fn new(
emit_cache: EmitCache, emit_cache: Arc<EmitCache>,
parsed_source_cache: Arc<ParsedSourceCache>, parsed_source_cache: Arc<ParsedSourceCache>,
transpile_options: deno_ast::TranspileOptions, transpile_options: deno_ast::TranspileOptions,
emit_options: deno_ast::EmitOptions, emit_options: deno_ast::EmitOptions,

View file

@ -164,7 +164,7 @@ struct CliFactoryServices {
global_http_cache: Deferred<Arc<GlobalHttpCache>>, global_http_cache: Deferred<Arc<GlobalHttpCache>>,
http_cache: Deferred<Arc<dyn HttpCache>>, http_cache: Deferred<Arc<dyn HttpCache>>,
http_client_provider: Deferred<Arc<HttpClientProvider>>, http_client_provider: Deferred<Arc<HttpClientProvider>>,
emit_cache: Deferred<EmitCache>, emit_cache: Deferred<Arc<EmitCache>>,
emitter: Deferred<Arc<Emitter>>, emitter: Deferred<Arc<Emitter>>,
fs: Deferred<Arc<dyn deno_fs::FileSystem>>, fs: Deferred<Arc<dyn deno_fs::FileSystem>>,
main_graph_container: Deferred<Arc<MainModuleGraphContainer>>, main_graph_container: Deferred<Arc<MainModuleGraphContainer>>,
@ -492,9 +492,9 @@ impl CliFactory {
.get_or_init(|| maybe_file_watcher_reporter) .get_or_init(|| maybe_file_watcher_reporter)
} }
pub fn emit_cache(&self) -> Result<&EmitCache, AnyError> { pub fn emit_cache(&self) -> Result<&Arc<EmitCache>, AnyError> {
self.services.emit_cache.get_or_try_init(|| { self.services.emit_cache.get_or_try_init(|| {
Ok(EmitCache::new(self.deno_dir()?.gen_cache.clone())) Ok(Arc::new(EmitCache::new(self.deno_dir()?.gen_cache.clone())))
}) })
} }

View file

@ -364,7 +364,7 @@ pub struct ModuleGraphBuilder {
parsed_source_cache: Arc<ParsedSourceCache>, parsed_source_cache: Arc<ParsedSourceCache>,
lockfile: Option<Arc<CliLockfile>>, lockfile: Option<Arc<CliLockfile>>,
maybe_file_watcher_reporter: Option<FileWatcherReporter>, maybe_file_watcher_reporter: Option<FileWatcherReporter>,
emit_cache: cache::EmitCache, emit_cache: Arc<cache::EmitCache>,
file_fetcher: Arc<FileFetcher>, file_fetcher: Arc<FileFetcher>,
global_http_cache: Arc<GlobalHttpCache>, global_http_cache: Arc<GlobalHttpCache>,
} }
@ -381,7 +381,7 @@ impl ModuleGraphBuilder {
parsed_source_cache: Arc<ParsedSourceCache>, parsed_source_cache: Arc<ParsedSourceCache>,
lockfile: Option<Arc<CliLockfile>>, lockfile: Option<Arc<CliLockfile>>,
maybe_file_watcher_reporter: Option<FileWatcherReporter>, maybe_file_watcher_reporter: Option<FileWatcherReporter>,
emit_cache: cache::EmitCache, emit_cache: Arc<cache::EmitCache>,
file_fetcher: Arc<FileFetcher>, file_fetcher: Arc<FileFetcher>,
global_http_cache: Arc<GlobalHttpCache>, global_http_cache: Arc<GlobalHttpCache>,
) -> Self { ) -> Self {

View file

@ -5342,3 +5342,20 @@ async fn listen_tls_alpn_fail() {
let status = child.wait().unwrap(); let status = child.wait().unwrap();
assert!(status.success()); assert!(status.success());
} }
// Couldn't get the directory readonly on windows on the CI
// so gave up because this being tested on unix is good enough
#[cfg(unix)]
#[test]
fn emit_failed_readonly_file_system() {
let context = TestContextBuilder::default().use_temp_cwd().build();
context.deno_dir().path().canonicalize().make_dir_readonly();
let temp_dir = context.temp_dir().path().canonicalize();
temp_dir.join("main.ts").write("import './other.ts';");
temp_dir.join("other.ts").write("console.log('hi');");
let output = context
.new_command()
.args("run --log-level=debug main.ts")
.run();
output.assert_matches_text("[WILDCARD]Error saving emit data ([WILDLINE]main.ts)[WILDCARD]Skipped emit cache save of [WILDLINE]other.ts[WILDCARD]hi[WILDCARD]");
}