mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
fix: use hash of in-memory bytes only for code cache (#23966)
* https://github.com/denoland/deno_core/pull/752 * https://github.com/denoland/deno_core/pull/753 Did benchmarking on this and it's slightly faster (couple ms) or equal to in performance as main. Closes #23904
This commit is contained in:
parent
92a8d09e49
commit
b21004b1d1
11 changed files with 93 additions and 174 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -1304,9 +1304,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_core"
|
name = "deno_core"
|
||||||
version = "0.282.0"
|
version = "0.283.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cde984155f9ec0986cb2b8e444ad675822968c5042ded50e32647f907eefd4b4"
|
checksum = "0f5043f9f636a3fe021e63e41c946499e1706d7565126065c60912fe5c77e54e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
|
@ -1754,9 +1754,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_ops"
|
name = "deno_ops"
|
||||||
version = "0.158.0"
|
version = "0.159.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f24983ce064294d3046f4fce5c53de4e6e08488c1d53f2387917f63f43cdfda8"
|
checksum = "b26cc5277982de16514282447f8674f9048d4f1b2c0d55c088d0a7d3bf6db385"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-rules",
|
"proc-macro-rules",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -1837,6 +1837,7 @@ dependencies = [
|
||||||
"test_server",
|
"test_server",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-metrics",
|
"tokio-metrics",
|
||||||
|
"twox-hash",
|
||||||
"uuid",
|
"uuid",
|
||||||
"which 4.4.2",
|
"which 4.4.2",
|
||||||
"winapi",
|
"winapi",
|
||||||
|
@ -5754,9 +5755,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_v8"
|
name = "serde_v8"
|
||||||
version = "0.191.0"
|
version = "0.192.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af3b1eaa93eacbbfc08f3fc18ff7418262781ebbeca3282e36a7f26d9c679b50"
|
checksum = "f7b616df6c4ff5643dd503cbfe119175ebebfd4132512e33de4971f1e91d5739"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
@ -44,7 +44,7 @@ repository = "https://github.com/denoland/deno"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
deno_ast = { version = "=0.38.2", features = ["transpiling"] }
|
deno_ast = { version = "=0.38.2", features = ["transpiling"] }
|
||||||
deno_core = { version = "0.282.0" }
|
deno_core = { version = "0.283.0" }
|
||||||
|
|
||||||
deno_bench_util = { version = "0.147.0", path = "./bench_util" }
|
deno_bench_util = { version = "0.147.0", path = "./bench_util" }
|
||||||
deno_lockfile = "0.19.0"
|
deno_lockfile = "0.19.0"
|
||||||
|
@ -174,6 +174,7 @@ tokio = { version = "1.36.0", features = ["full"] }
|
||||||
tokio-metrics = { version = "0.3.0", features = ["rt"] }
|
tokio-metrics = { version = "0.3.0", features = ["rt"] }
|
||||||
tokio-util = "0.7.4"
|
tokio-util = "0.7.4"
|
||||||
tower-lsp = { version = "=0.20.0", features = ["proposed"] }
|
tower-lsp = { version = "=0.20.0", features = ["proposed"] }
|
||||||
|
twox-hash = "=1.6.3"
|
||||||
# Upgrading past 2.4.1 may cause WPT failures
|
# Upgrading past 2.4.1 may cause WPT failures
|
||||||
url = { version = "< 2.5.0", features = ["serde", "expose_internals"] }
|
url = { version = "< 2.5.0", features = ["serde", "expose_internals"] }
|
||||||
uuid = { version = "1.3.0", features = ["v4"] }
|
uuid = { version = "1.3.0", features = ["v4"] }
|
||||||
|
|
|
@ -146,7 +146,7 @@ thiserror.workspace = true
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
tokio-util.workspace = true
|
tokio-util.workspace = true
|
||||||
tower-lsp.workspace = true
|
tower-lsp.workspace = true
|
||||||
twox-hash = "=1.6.3"
|
twox-hash.workspace = true
|
||||||
typed-arena = "=2.0.1"
|
typed-arena = "=2.0.1"
|
||||||
uuid = { workspace = true, features = ["serde"] }
|
uuid = { workspace = true, features = ["serde"] }
|
||||||
walkdir = "=2.3.2"
|
walkdir = "=2.3.2"
|
||||||
|
|
31
cli/cache/code_cache.rs
vendored
31
cli/cache/code_cache.rs
vendored
|
@ -1,5 +1,6 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use deno_ast::ModuleSpecifier;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_runtime::code_cache;
|
use deno_runtime::code_cache;
|
||||||
use deno_runtime::deno_webstorage::rusqlite::params;
|
use deno_runtime::deno_webstorage::rusqlite::params;
|
||||||
|
@ -21,7 +22,6 @@ pub static CODE_CACHE_DB: CacheDBConfiguration = CacheDBConfiguration {
|
||||||
on_failure: CacheFailure::Blackhole,
|
on_failure: CacheFailure::Blackhole,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct CodeCache {
|
pub struct CodeCache {
|
||||||
inner: CodeCacheInner,
|
inner: CodeCacheInner,
|
||||||
}
|
}
|
||||||
|
@ -52,28 +52,28 @@ impl CodeCache {
|
||||||
|
|
||||||
pub fn get_sync(
|
pub fn get_sync(
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &ModuleSpecifier,
|
||||||
code_cache_type: code_cache::CodeCacheType,
|
code_cache_type: code_cache::CodeCacheType,
|
||||||
source_hash: &str,
|
source_hash: u64,
|
||||||
) -> Option<Vec<u8>> {
|
) -> Option<Vec<u8>> {
|
||||||
Self::ensure_ok(self.inner.get_sync(
|
Self::ensure_ok(self.inner.get_sync(
|
||||||
specifier,
|
specifier.as_str(),
|
||||||
code_cache_type,
|
code_cache_type,
|
||||||
source_hash,
|
&source_hash.to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_sync(
|
pub fn set_sync(
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &ModuleSpecifier,
|
||||||
code_cache_type: code_cache::CodeCacheType,
|
code_cache_type: code_cache::CodeCacheType,
|
||||||
source_hash: &str,
|
source_hash: u64,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) {
|
) {
|
||||||
Self::ensure_ok(self.inner.set_sync(
|
Self::ensure_ok(self.inner.set_sync(
|
||||||
specifier,
|
specifier.as_str(),
|
||||||
code_cache_type,
|
code_cache_type,
|
||||||
source_hash,
|
&source_hash.to_string(),
|
||||||
data,
|
data,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -82,25 +82,24 @@ impl CodeCache {
|
||||||
impl code_cache::CodeCache for CodeCache {
|
impl code_cache::CodeCache for CodeCache {
|
||||||
fn get_sync(
|
fn get_sync(
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &ModuleSpecifier,
|
||||||
code_cache_type: code_cache::CodeCacheType,
|
code_cache_type: code_cache::CodeCacheType,
|
||||||
source_hash: &str,
|
source_hash: u64,
|
||||||
) -> Option<Vec<u8>> {
|
) -> Option<Vec<u8>> {
|
||||||
self.get_sync(specifier, code_cache_type, source_hash)
|
self.get_sync(specifier, code_cache_type, source_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_sync(
|
fn set_sync(
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: ModuleSpecifier,
|
||||||
code_cache_type: code_cache::CodeCacheType,
|
code_cache_type: code_cache::CodeCacheType,
|
||||||
source_hash: &str,
|
source_hash: u64,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) {
|
) {
|
||||||
self.set_sync(specifier, code_cache_type, source_hash, data);
|
self.set_sync(&specifier, code_cache_type, source_hash, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct CodeCacheInner {
|
struct CodeCacheInner {
|
||||||
conn: CacheDB,
|
conn: CacheDB,
|
||||||
}
|
}
|
||||||
|
@ -135,7 +134,7 @@ impl CodeCacheInner {
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
code_cache_type: code_cache::CodeCacheType,
|
code_cache_type: code_cache::CodeCacheType,
|
||||||
source_hash: &str,
|
source_hash: &str, // use string because sqlite doesn't have a u64 type
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let sql = "
|
let sql = "
|
||||||
|
|
17
cli/cache/module_info.rs
vendored
17
cli/cache/module_info.rs
vendored
|
@ -87,23 +87,6 @@ impl ModuleInfoCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_module_source_hash(
|
|
||||||
&self,
|
|
||||||
specifier: &ModuleSpecifier,
|
|
||||||
media_type: MediaType,
|
|
||||||
) -> Result<Option<ModuleInfoCacheSourceHash>, AnyError> {
|
|
||||||
let query = "SELECT source_hash FROM moduleinfocache WHERE specifier=?1 AND media_type=?2";
|
|
||||||
let res = self.conn.query_row(
|
|
||||||
query,
|
|
||||||
params![specifier.as_str(), serialize_media_type(media_type)],
|
|
||||||
|row| {
|
|
||||||
let source_hash: String = row.get(0)?;
|
|
||||||
Ok(ModuleInfoCacheSourceHash(source_hash))
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_module_info(
|
pub fn get_module_info(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
|
|
@ -798,7 +798,6 @@ impl CliFactory {
|
||||||
},
|
},
|
||||||
self.emitter()?.clone(),
|
self.emitter()?.clone(),
|
||||||
self.main_module_graph_container().await?.clone(),
|
self.main_module_graph_container().await?.clone(),
|
||||||
self.module_info_cache()?.clone(),
|
|
||||||
self.module_load_preparer().await?.clone(),
|
self.module_load_preparer().await?.clone(),
|
||||||
cli_node_resolver.clone(),
|
cli_node_resolver.clone(),
|
||||||
NpmModuleLoader::new(
|
NpmModuleLoader::new(
|
||||||
|
|
|
@ -13,7 +13,7 @@ use crate::args::CliOptions;
|
||||||
use crate::args::DenoSubcommand;
|
use crate::args::DenoSubcommand;
|
||||||
use crate::args::TsTypeLib;
|
use crate::args::TsTypeLib;
|
||||||
use crate::cache::CodeCache;
|
use crate::cache::CodeCache;
|
||||||
use crate::cache::ModuleInfoCache;
|
use crate::cache::FastInsecureHasher;
|
||||||
use crate::cache::ParsedSourceCache;
|
use crate::cache::ParsedSourceCache;
|
||||||
use crate::emit::Emitter;
|
use crate::emit::Emitter;
|
||||||
use crate::factory::CliFactory;
|
use crate::factory::CliFactory;
|
||||||
|
@ -55,6 +55,7 @@ use deno_core::ModuleSpecifier;
|
||||||
use deno_core::ModuleType;
|
use deno_core::ModuleType;
|
||||||
use deno_core::RequestedModuleType;
|
use deno_core::RequestedModuleType;
|
||||||
use deno_core::ResolutionKind;
|
use deno_core::ResolutionKind;
|
||||||
|
use deno_core::SourceCodeCacheInfo;
|
||||||
use deno_core::SourceMapGetter;
|
use deno_core::SourceMapGetter;
|
||||||
use deno_graph::source::ResolutionMode;
|
use deno_graph::source::ResolutionMode;
|
||||||
use deno_graph::source::Resolver;
|
use deno_graph::source::Resolver;
|
||||||
|
@ -67,7 +68,6 @@ use deno_graph::Resolution;
|
||||||
use deno_lockfile::Lockfile;
|
use deno_lockfile::Lockfile;
|
||||||
use deno_runtime::code_cache;
|
use deno_runtime::code_cache;
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
use deno_runtime::deno_node::NodeResolutionMode;
|
||||||
use deno_runtime::fs_util::code_timestamp;
|
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
|
||||||
|
@ -221,7 +221,6 @@ struct SharedCliModuleLoaderState {
|
||||||
code_cache: Option<Arc<CodeCache>>,
|
code_cache: Option<Arc<CodeCache>>,
|
||||||
emitter: Arc<Emitter>,
|
emitter: Arc<Emitter>,
|
||||||
main_module_graph_container: Arc<MainModuleGraphContainer>,
|
main_module_graph_container: Arc<MainModuleGraphContainer>,
|
||||||
module_info_cache: Arc<ModuleInfoCache>,
|
|
||||||
module_load_preparer: Arc<ModuleLoadPreparer>,
|
module_load_preparer: Arc<ModuleLoadPreparer>,
|
||||||
node_resolver: Arc<CliNodeResolver>,
|
node_resolver: Arc<CliNodeResolver>,
|
||||||
npm_module_loader: NpmModuleLoader,
|
npm_module_loader: NpmModuleLoader,
|
||||||
|
@ -240,7 +239,6 @@ impl CliModuleLoaderFactory {
|
||||||
code_cache: Option<Arc<CodeCache>>,
|
code_cache: Option<Arc<CodeCache>>,
|
||||||
emitter: Arc<Emitter>,
|
emitter: Arc<Emitter>,
|
||||||
main_module_graph_container: Arc<MainModuleGraphContainer>,
|
main_module_graph_container: Arc<MainModuleGraphContainer>,
|
||||||
module_info_cache: Arc<ModuleInfoCache>,
|
|
||||||
module_load_preparer: Arc<ModuleLoadPreparer>,
|
module_load_preparer: Arc<ModuleLoadPreparer>,
|
||||||
node_resolver: Arc<CliNodeResolver>,
|
node_resolver: Arc<CliNodeResolver>,
|
||||||
npm_module_loader: NpmModuleLoader,
|
npm_module_loader: NpmModuleLoader,
|
||||||
|
@ -261,7 +259,6 @@ impl CliModuleLoaderFactory {
|
||||||
code_cache,
|
code_cache,
|
||||||
emitter,
|
emitter,
|
||||||
main_module_graph_container,
|
main_module_graph_container,
|
||||||
module_info_cache,
|
|
||||||
module_load_preparer,
|
module_load_preparer,
|
||||||
node_resolver,
|
node_resolver,
|
||||||
npm_module_loader,
|
npm_module_loader,
|
||||||
|
@ -388,27 +385,20 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
}
|
}
|
||||||
|
|
||||||
let code_cache = if module_type == ModuleType::JavaScript {
|
let code_cache = if module_type == ModuleType::JavaScript {
|
||||||
self.shared.code_cache.as_ref().and_then(|cache| {
|
self.shared.code_cache.as_ref().map(|cache| {
|
||||||
let code_hash = self
|
let code_hash = FastInsecureHasher::hash(&code);
|
||||||
.get_code_hash_or_timestamp(specifier, code_source.media_type)
|
let data = cache
|
||||||
.ok()
|
.get_sync(specifier, code_cache::CodeCacheType::EsModule, code_hash)
|
||||||
.flatten();
|
.map(Cow::from)
|
||||||
if let Some(code_hash) = code_hash {
|
.inspect(|_| {
|
||||||
cache
|
// This log line is also used by tests.
|
||||||
.get_sync(
|
log::debug!(
|
||||||
specifier.as_str(),
|
"V8 code cache hit for ES module: {specifier}, [{code_hash:?}]"
|
||||||
code_cache::CodeCacheType::EsModule,
|
);
|
||||||
&code_hash,
|
});
|
||||||
)
|
SourceCodeCacheInfo {
|
||||||
.map(Cow::from)
|
hash: code_hash,
|
||||||
.inspect(|_| {
|
data,
|
||||||
// This log line is also used by tests.
|
|
||||||
log::debug!(
|
|
||||||
"V8 code cache hit for ES module: {specifier}, [{code_hash:?}]"
|
|
||||||
);
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -589,25 +579,6 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
resolution.map_err(|err| err.into())
|
resolution.map_err(|err| err.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_code_hash_or_timestamp(
|
|
||||||
&self,
|
|
||||||
specifier: &ModuleSpecifier,
|
|
||||||
media_type: MediaType,
|
|
||||||
) -> Result<Option<String>, AnyError> {
|
|
||||||
let hash = self
|
|
||||||
.shared
|
|
||||||
.module_info_cache
|
|
||||||
.get_module_source_hash(specifier, media_type)?;
|
|
||||||
if let Some(hash) = hash {
|
|
||||||
return Ok(Some(hash.into()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the modified timestamp from the local file system if we don't have a hash.
|
|
||||||
let timestamp = code_timestamp(specifier.as_str())
|
|
||||||
.map(|timestamp| timestamp.to_string())?;
|
|
||||||
Ok(Some(timestamp))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn load_prepared_module(
|
async fn load_prepared_module(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
@ -865,28 +836,21 @@ impl<TGraphContainer: ModuleGraphContainer> ModuleLoader
|
||||||
|
|
||||||
fn code_cache_ready(
|
fn code_cache_ready(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: ModuleSpecifier,
|
||||||
|
source_hash: u64,
|
||||||
code_cache: &[u8],
|
code_cache: &[u8],
|
||||||
) -> Pin<Box<dyn Future<Output = ()>>> {
|
) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||||
if let Some(cache) = self.0.shared.code_cache.as_ref() {
|
if let Some(cache) = self.0.shared.code_cache.as_ref() {
|
||||||
let media_type = MediaType::from_specifier(specifier);
|
// This log line is also used by tests.
|
||||||
let code_hash = self
|
log::debug!(
|
||||||
.0
|
"Updating V8 code cache for ES module: {specifier}, [{source_hash:?}]"
|
||||||
.get_code_hash_or_timestamp(specifier, media_type)
|
);
|
||||||
.ok()
|
cache.set_sync(
|
||||||
.flatten();
|
&specifier,
|
||||||
if let Some(code_hash) = code_hash {
|
code_cache::CodeCacheType::EsModule,
|
||||||
// This log line is also used by tests.
|
source_hash,
|
||||||
log::debug!(
|
code_cache,
|
||||||
"Updating V8 code cache for ES module: {specifier}, [{code_hash:?}]"
|
);
|
||||||
);
|
|
||||||
cache.set_sync(
|
|
||||||
specifier.as_str(),
|
|
||||||
code_cache::CodeCacheType::EsModule,
|
|
||||||
&code_hash,
|
|
||||||
code_cache,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
std::future::ready(()).boxed_local()
|
std::future::ready(()).boxed_local()
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,7 @@ signal-hook = "0.3.17"
|
||||||
signal-hook-registry = "1.4.0"
|
signal-hook-registry = "1.4.0"
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
tokio-metrics.workspace = true
|
tokio-metrics.workspace = true
|
||||||
|
twox-hash.workspace = true
|
||||||
uuid.workspace = true
|
uuid.workspace = true
|
||||||
which = "4.2.5"
|
which = "4.2.5"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use deno_core::ModuleSpecifier;
|
||||||
|
|
||||||
pub enum CodeCacheType {
|
pub enum CodeCacheType {
|
||||||
EsModule,
|
EsModule,
|
||||||
Script,
|
Script,
|
||||||
|
@ -17,15 +19,15 @@ impl CodeCacheType {
|
||||||
pub trait CodeCache: Send + Sync {
|
pub trait CodeCache: Send + Sync {
|
||||||
fn get_sync(
|
fn get_sync(
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &ModuleSpecifier,
|
||||||
code_cache_type: CodeCacheType,
|
code_cache_type: CodeCacheType,
|
||||||
source_hash: &str,
|
source_hash: u64,
|
||||||
) -> Option<Vec<u8>>;
|
) -> Option<Vec<u8>>;
|
||||||
fn set_sync(
|
fn set_sync(
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: ModuleSpecifier,
|
||||||
code_cache_type: CodeCacheType,
|
code_cache_type: CodeCacheType,
|
||||||
source_hash: &str,
|
source_hash: u64,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,17 +63,6 @@ pub fn specifier_to_file_path(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn code_timestamp(specifier: &str) -> Result<u64, AnyError> {
|
|
||||||
let specifier = ModuleSpecifier::parse(specifier)?;
|
|
||||||
let path = specifier_to_file_path(&specifier)?;
|
|
||||||
#[allow(clippy::disallowed_methods)]
|
|
||||||
let timestamp = std::fs::metadata(path)?
|
|
||||||
.modified()?
|
|
||||||
.duration_since(std::time::UNIX_EPOCH)?
|
|
||||||
.as_millis() as u64;
|
|
||||||
Ok(timestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -32,6 +32,7 @@ use deno_core::OpMetricsSummaryTracker;
|
||||||
use deno_core::PollEventLoopOptions;
|
use deno_core::PollEventLoopOptions;
|
||||||
use deno_core::RuntimeOptions;
|
use deno_core::RuntimeOptions;
|
||||||
use deno_core::SharedArrayBufferStore;
|
use deno_core::SharedArrayBufferStore;
|
||||||
|
use deno_core::SourceCodeCacheInfo;
|
||||||
use deno_core::SourceMapGetter;
|
use deno_core::SourceMapGetter;
|
||||||
use deno_cron::local::LocalCronHandler;
|
use deno_cron::local::LocalCronHandler;
|
||||||
use deno_fs::FileSystem;
|
use deno_fs::FileSystem;
|
||||||
|
@ -45,7 +46,6 @@ use log::debug;
|
||||||
|
|
||||||
use crate::code_cache::CodeCache;
|
use crate::code_cache::CodeCache;
|
||||||
use crate::code_cache::CodeCacheType;
|
use crate::code_cache::CodeCacheType;
|
||||||
use crate::fs_util::code_timestamp;
|
|
||||||
use crate::inspector_server::InspectorServer;
|
use crate::inspector_server::InspectorServer;
|
||||||
use crate::ops;
|
use crate::ops;
|
||||||
use crate::permissions::PermissionsContainer;
|
use crate::permissions::PermissionsContainer;
|
||||||
|
@ -306,51 +306,6 @@ pub fn create_op_metrics(
|
||||||
(op_summary_metrics, op_metrics_factory_fn)
|
(op_summary_metrics, op_metrics_factory_fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_code_cache(
|
|
||||||
code_cache: Arc<dyn CodeCache>,
|
|
||||||
specifier: &str,
|
|
||||||
) -> Option<Vec<u8>> {
|
|
||||||
// Code hashes are not maintained for op_eval_context scripts. Instead we use
|
|
||||||
// the modified timestamp from the local file system.
|
|
||||||
if let Ok(code_timestamp) = code_timestamp(specifier) {
|
|
||||||
code_cache
|
|
||||||
.get_sync(
|
|
||||||
specifier,
|
|
||||||
CodeCacheType::Script,
|
|
||||||
code_timestamp.to_string().as_str(),
|
|
||||||
)
|
|
||||||
.inspect(|_| {
|
|
||||||
// This log line is also used by tests.
|
|
||||||
log::debug!(
|
|
||||||
"V8 code cache hit for script: {specifier}, [{code_timestamp}]"
|
|
||||||
);
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_code_cache(
|
|
||||||
code_cache: Arc<dyn CodeCache>,
|
|
||||||
specifier: &str,
|
|
||||||
data: &[u8],
|
|
||||||
) {
|
|
||||||
// Code hashes are not maintained for op_eval_context scripts. Instead we use
|
|
||||||
// the modified timestamp from the local file system.
|
|
||||||
if let Ok(code_timestamp) = code_timestamp(specifier) {
|
|
||||||
// This log line is also used by tests.
|
|
||||||
log::debug!(
|
|
||||||
"Updating V8 code cache for script: {specifier}, [{code_timestamp}]",
|
|
||||||
);
|
|
||||||
code_cache.set_sync(
|
|
||||||
specifier,
|
|
||||||
CodeCacheType::Script,
|
|
||||||
code_timestamp.to_string().as_str(),
|
|
||||||
data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MainWorker {
|
impl MainWorker {
|
||||||
pub fn bootstrap_from_options(
|
pub fn bootstrap_from_options(
|
||||||
main_module: ModuleSpecifier,
|
main_module: ModuleSpecifier,
|
||||||
|
@ -550,16 +505,41 @@ impl MainWorker {
|
||||||
validate_import_attributes_cb: Some(Box::new(
|
validate_import_attributes_cb: Some(Box::new(
|
||||||
validate_import_attributes_callback,
|
validate_import_attributes_callback,
|
||||||
)),
|
)),
|
||||||
enable_code_cache: options.v8_code_cache.is_some(),
|
|
||||||
eval_context_code_cache_cbs: options.v8_code_cache.map(|cache| {
|
eval_context_code_cache_cbs: options.v8_code_cache.map(|cache| {
|
||||||
let cache_clone = cache.clone();
|
let cache_clone = cache.clone();
|
||||||
(
|
(
|
||||||
Box::new(move |specifier: &str| {
|
Box::new(move |specifier: &ModuleSpecifier, code: &v8::String| {
|
||||||
Ok(get_code_cache(cache.clone(), specifier).map(Cow::Owned))
|
let source_hash = {
|
||||||
}) as Box<dyn Fn(&_) -> _>,
|
use std::hash::Hash;
|
||||||
Box::new(move |specifier: &str, data: &[u8]| {
|
use std::hash::Hasher;
|
||||||
set_code_cache(cache_clone.clone(), specifier, data);
|
let mut hasher = twox_hash::XxHash64::default();
|
||||||
}) as Box<dyn Fn(&_, &_)>,
|
code.hash(&mut hasher);
|
||||||
|
hasher.finish()
|
||||||
|
};
|
||||||
|
let data = cache
|
||||||
|
.get_sync(specifier, CodeCacheType::Script, source_hash)
|
||||||
|
.inspect(|_| {
|
||||||
|
// This log line is also used by tests.
|
||||||
|
log::debug!("V8 code cache hit for script: {specifier}, [{source_hash}]");
|
||||||
|
})
|
||||||
|
.map(Cow::Owned);
|
||||||
|
Ok(SourceCodeCacheInfo {
|
||||||
|
data,
|
||||||
|
hash: source_hash,
|
||||||
|
})
|
||||||
|
}) as Box<dyn Fn(&_, &_) -> _>,
|
||||||
|
Box::new(
|
||||||
|
move |specifier: ModuleSpecifier, source_hash: u64, data: &[u8]| {
|
||||||
|
// This log line is also used by tests.
|
||||||
|
log::debug!("Updating V8 code cache for script: {specifier}, [{source_hash}]");
|
||||||
|
cache_clone.set_sync(
|
||||||
|
specifier,
|
||||||
|
CodeCacheType::Script,
|
||||||
|
source_hash,
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
) as Box<dyn Fn(_, _, &_)>,
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
Loading…
Reference in a new issue