mirror of
https://github.com/denoland/deno.git
synced 2025-08-03 10:33:54 +00:00
perf(jsr): fast check cache and lazy fast check graph (#22485)
This commit is contained in:
parent
dbc4a4d632
commit
f90889e5ee
25 changed files with 669 additions and 220 deletions
|
@ -22,10 +22,8 @@ use crate::util::path::specifier_to_file_path;
|
|||
use crate::util::sync::TaskQueue;
|
||||
use crate::util::sync::TaskQueuePermit;
|
||||
|
||||
use deno_config::ConfigFile;
|
||||
use deno_config::WorkspaceMemberConfig;
|
||||
use deno_core::anyhow::bail;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::parking_lot::Mutex;
|
||||
|
@ -208,56 +206,34 @@ pub struct CreateGraphOptions<'a> {
|
|||
pub graph_kind: GraphKind,
|
||||
pub roots: Vec<ModuleSpecifier>,
|
||||
pub is_dynamic: bool,
|
||||
/// Whether to do fast check on workspace members. This is mostly only
|
||||
/// useful when publishing.
|
||||
pub workspace_fast_check: bool,
|
||||
/// Specify `None` to use the default CLI loader.
|
||||
pub loader: Option<&'a mut dyn Loader>,
|
||||
}
|
||||
|
||||
pub struct ModuleGraphBuilder {
|
||||
pub struct ModuleGraphCreator {
|
||||
options: Arc<CliOptions>,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
resolver: Arc<CliGraphResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
module_info_cache: Arc<ModuleInfoCache>,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||
lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
||||
emit_cache: cache::EmitCache,
|
||||
file_fetcher: Arc<FileFetcher>,
|
||||
global_http_cache: Arc<GlobalHttpCache>,
|
||||
type_checker: Arc<TypeChecker>,
|
||||
}
|
||||
|
||||
impl ModuleGraphBuilder {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
impl ModuleGraphCreator {
|
||||
pub fn new(
|
||||
options: Arc<CliOptions>,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
resolver: Arc<CliGraphResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
module_info_cache: Arc<ModuleInfoCache>,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||
lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
||||
emit_cache: cache::EmitCache,
|
||||
file_fetcher: Arc<FileFetcher>,
|
||||
global_http_cache: Arc<GlobalHttpCache>,
|
||||
type_checker: Arc<TypeChecker>,
|
||||
) -> Self {
|
||||
Self {
|
||||
options,
|
||||
fs,
|
||||
resolver,
|
||||
npm_resolver,
|
||||
module_info_cache,
|
||||
parsed_source_cache,
|
||||
lockfile,
|
||||
maybe_file_watcher_reporter,
|
||||
emit_cache,
|
||||
file_fetcher,
|
||||
global_http_cache,
|
||||
module_graph_builder,
|
||||
type_checker,
|
||||
}
|
||||
}
|
||||
|
@ -267,7 +243,7 @@ impl ModuleGraphBuilder {
|
|||
graph_kind: GraphKind,
|
||||
roots: Vec<ModuleSpecifier>,
|
||||
) -> Result<deno_graph::ModuleGraph, AnyError> {
|
||||
let mut cache = self.create_graph_loader();
|
||||
let mut cache = self.module_graph_builder.create_graph_loader();
|
||||
self
|
||||
.create_graph_with_loader(graph_kind, roots, &mut cache)
|
||||
.await
|
||||
|
@ -285,7 +261,6 @@ impl ModuleGraphBuilder {
|
|||
graph_kind,
|
||||
roots,
|
||||
loader: Some(loader),
|
||||
workspace_fast_check: false,
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
@ -298,15 +273,21 @@ impl ModuleGraphBuilder {
|
|||
for package in packages {
|
||||
roots.extend(package.config_file.resolve_export_value_urls()?);
|
||||
}
|
||||
self
|
||||
let mut graph = self
|
||||
.create_graph_with_options(CreateGraphOptions {
|
||||
is_dynamic: false,
|
||||
graph_kind: deno_graph::GraphKind::All,
|
||||
roots,
|
||||
workspace_fast_check: true,
|
||||
loader: None,
|
||||
})
|
||||
.await
|
||||
.await?;
|
||||
self.module_graph_builder.build_fast_check_graph(
|
||||
&mut graph,
|
||||
BuildFastCheckGraphOptions {
|
||||
workspace_fast_check: true,
|
||||
},
|
||||
)?;
|
||||
Ok(graph)
|
||||
}
|
||||
|
||||
pub async fn create_graph_with_options(
|
||||
|
@ -316,6 +297,7 @@ impl ModuleGraphBuilder {
|
|||
let mut graph = ModuleGraph::new(options.graph_kind);
|
||||
|
||||
self
|
||||
.module_graph_builder
|
||||
.build_graph_with_npm_resolution(&mut graph, options)
|
||||
.await?;
|
||||
|
||||
|
@ -340,11 +322,9 @@ impl ModuleGraphBuilder {
|
|||
graph_kind,
|
||||
roots,
|
||||
loader: None,
|
||||
workspace_fast_check: false,
|
||||
})
|
||||
.await?;
|
||||
|
||||
let graph = Arc::new(graph);
|
||||
graph_valid_with_cli_options(
|
||||
&graph,
|
||||
self.fs.as_ref(),
|
||||
|
@ -356,43 +336,76 @@ impl ModuleGraphBuilder {
|
|||
}
|
||||
|
||||
if self.options.type_check_mode().is_true() {
|
||||
self
|
||||
// provide the graph to the type checker, then get it back after it's done
|
||||
let graph = self
|
||||
.type_checker
|
||||
.check(
|
||||
graph.clone(),
|
||||
graph,
|
||||
check::CheckOptions {
|
||||
build_fast_check_graph: true,
|
||||
lib: self.options.ts_type_lib_window(),
|
||||
log_ignored_options: true,
|
||||
reload: self.options.reload_flag(),
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(graph)
|
||||
}
|
||||
|
||||
fn get_deno_graph_workspace_members(
|
||||
&self,
|
||||
) -> Result<Vec<deno_graph::WorkspaceMember>, AnyError> {
|
||||
let maybe_workspace_config = self.options.maybe_workspace_config();
|
||||
if let Some(wc) = maybe_workspace_config {
|
||||
workspace_config_to_workspace_members(wc)
|
||||
Ok(graph)
|
||||
} else {
|
||||
Ok(
|
||||
self
|
||||
.options
|
||||
.maybe_config_file()
|
||||
.as_ref()
|
||||
.and_then(|c| match config_to_workspace_member(c) {
|
||||
Ok(m) => Some(vec![m]),
|
||||
Err(e) => {
|
||||
log::debug!("Deno config was not a package: {:#}", e);
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
Ok(Arc::new(graph))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BuildFastCheckGraphOptions {
|
||||
/// Whether to do fast check on workspace members. This
|
||||
/// is mostly only useful when publishing.
|
||||
pub workspace_fast_check: bool,
|
||||
}
|
||||
|
||||
pub struct ModuleGraphBuilder {
|
||||
options: Arc<CliOptions>,
|
||||
caches: Arc<cache::Caches>,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
resolver: Arc<CliGraphResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
module_info_cache: Arc<ModuleInfoCache>,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
||||
emit_cache: cache::EmitCache,
|
||||
file_fetcher: Arc<FileFetcher>,
|
||||
global_http_cache: Arc<GlobalHttpCache>,
|
||||
}
|
||||
|
||||
impl ModuleGraphBuilder {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
options: Arc<CliOptions>,
|
||||
caches: Arc<cache::Caches>,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
resolver: Arc<CliGraphResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
module_info_cache: Arc<ModuleInfoCache>,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
||||
emit_cache: cache::EmitCache,
|
||||
file_fetcher: Arc<FileFetcher>,
|
||||
global_http_cache: Arc<GlobalHttpCache>,
|
||||
) -> Self {
|
||||
Self {
|
||||
options,
|
||||
caches,
|
||||
fs,
|
||||
resolver,
|
||||
npm_resolver,
|
||||
module_info_cache,
|
||||
parsed_source_cache,
|
||||
lockfile,
|
||||
maybe_file_watcher_reporter,
|
||||
emit_cache,
|
||||
file_fetcher,
|
||||
global_http_cache,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,13 +435,15 @@ impl ModuleGraphBuilder {
|
|||
Some(loader) => MutLoaderRef::Borrowed(loader),
|
||||
None => MutLoaderRef::Owned(self.create_graph_loader()),
|
||||
};
|
||||
let cli_resolver = self.resolver.clone();
|
||||
let cli_resolver = &self.resolver;
|
||||
let graph_resolver = cli_resolver.as_graph_resolver();
|
||||
let graph_npm_resolver = cli_resolver.as_graph_npm_resolver();
|
||||
let maybe_file_watcher_reporter = self
|
||||
.maybe_file_watcher_reporter
|
||||
.as_ref()
|
||||
.map(|r| r.as_reporter());
|
||||
let workspace_members =
|
||||
self.options.resolve_deno_graph_workspace_members()?;
|
||||
self
|
||||
.build_graph_with_npm_resolution_and_build_options(
|
||||
graph,
|
||||
|
@ -436,6 +451,7 @@ impl ModuleGraphBuilder {
|
|||
loader.as_mut_loader(),
|
||||
deno_graph::BuildOptions {
|
||||
is_dynamic: options.is_dynamic,
|
||||
jsr_url_provider: Some(&CliJsrUrlProvider),
|
||||
imports: maybe_imports,
|
||||
resolver: Some(graph_resolver),
|
||||
file_system: Some(&DenoGraphFsAdapter(self.fs.as_ref())),
|
||||
|
@ -443,8 +459,7 @@ impl ModuleGraphBuilder {
|
|||
module_analyzer: Some(&analyzer),
|
||||
module_parser: Some(&parser),
|
||||
reporter: maybe_file_watcher_reporter,
|
||||
workspace_fast_check: options.workspace_fast_check,
|
||||
workspace_members: self.get_deno_graph_workspace_members()?,
|
||||
workspace_members: &workspace_members,
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
@ -567,6 +582,49 @@ impl ModuleGraphBuilder {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn build_fast_check_graph(
|
||||
&self,
|
||||
graph: &mut ModuleGraph,
|
||||
options: BuildFastCheckGraphOptions,
|
||||
) -> Result<(), AnyError> {
|
||||
if !graph.graph_kind().include_types() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
log::debug!("Building fast check graph");
|
||||
let fast_check_cache = if !options.workspace_fast_check {
|
||||
Some(cache::FastCheckCache::new(self.caches.fast_check_db()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let parser = self.parsed_source_cache.as_capturing_parser();
|
||||
let cli_resolver = &self.resolver;
|
||||
let graph_resolver = cli_resolver.as_graph_resolver();
|
||||
let graph_npm_resolver = cli_resolver.as_graph_npm_resolver();
|
||||
let workspace_members = if options.workspace_fast_check {
|
||||
Some(self.options.resolve_deno_graph_workspace_members()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
graph.build_fast_check_type_graph(
|
||||
deno_graph::BuildFastCheckTypeGraphOptions {
|
||||
jsr_url_provider: Some(&CliJsrUrlProvider),
|
||||
fast_check_cache: fast_check_cache.as_ref().map(|c| c as _),
|
||||
fast_check_dts: false,
|
||||
module_parser: Some(&parser),
|
||||
resolver: Some(graph_resolver),
|
||||
npm_resolver: Some(graph_npm_resolver),
|
||||
workspace_fast_check: if let Some(members) = &workspace_members {
|
||||
deno_graph::WorkspaceFastCheckOption::Enabled(members)
|
||||
} else {
|
||||
deno_graph::WorkspaceFastCheckOption::Disabled
|
||||
},
|
||||
},
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Creates the default loader used for creating a graph.
|
||||
pub fn create_graph_loader(&self) -> cache::FetchCacher {
|
||||
self.create_fetch_cacher(PermissionsContainer::allow_all())
|
||||
|
@ -851,44 +909,6 @@ impl deno_graph::source::Reporter for FileWatcherReporter {
|
|||
}
|
||||
}
|
||||
|
||||
fn workspace_config_to_workspace_members(
|
||||
workspace_config: &deno_config::WorkspaceConfig,
|
||||
) -> Result<Vec<deno_graph::WorkspaceMember>, AnyError> {
|
||||
workspace_config
|
||||
.members
|
||||
.iter()
|
||||
.map(|member| {
|
||||
config_to_workspace_member(&member.config_file).with_context(|| {
|
||||
format!(
|
||||
"Failed to resolve configuration for '{}' workspace member at '{}'",
|
||||
member.member_name,
|
||||
member.config_file.specifier.as_str()
|
||||
)
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn config_to_workspace_member(
|
||||
config: &ConfigFile,
|
||||
) -> Result<deno_graph::WorkspaceMember, AnyError> {
|
||||
let nv = deno_semver::package::PackageNv {
|
||||
name: match &config.json.name {
|
||||
Some(name) => name.clone(),
|
||||
None => bail!("Missing 'name' field in config file."),
|
||||
},
|
||||
version: match &config.json.version {
|
||||
Some(name) => deno_semver::Version::parse_standard(name)?,
|
||||
None => bail!("Missing 'version' field in config file."),
|
||||
},
|
||||
};
|
||||
Ok(deno_graph::WorkspaceMember {
|
||||
base: config.specifier.join("./").unwrap(),
|
||||
nv,
|
||||
exports: config.to_exports_config()?.into_map(),
|
||||
})
|
||||
}
|
||||
|
||||
pub struct DenoGraphFsAdapter<'a>(
|
||||
pub &'a dyn deno_runtime::deno_fs::FileSystem,
|
||||
);
|
||||
|
@ -963,6 +983,15 @@ pub fn format_range_with_colors(range: &deno_graph::Range) -> String {
|
|||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
struct CliJsrUrlProvider;
|
||||
|
||||
impl deno_graph::source::JsrUrlProvider for CliJsrUrlProvider {
|
||||
fn url(&self) -> &'static ModuleSpecifier {
|
||||
jsr_url()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::sync::Arc;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue