1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 23:34:47 -05:00

perf: resolver - skip cwd lookup if able (#23851)

The cwd lookup was taking 2% of a flamegraph I was looking at.
This commit is contained in:
David Sherret 2024-05-21 10:38:06 -04:00 committed by GitHub
parent 3d6ba1eaf1
commit 54eb930e8c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -2,6 +2,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
use std::path::PathBuf;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use std::str; use std::str;
@ -214,6 +215,7 @@ struct SharedCliModuleLoaderState {
graph_kind: GraphKind, graph_kind: GraphKind,
lib_window: TsTypeLib, lib_window: TsTypeLib,
lib_worker: TsTypeLib, lib_worker: TsTypeLib,
initial_cwd: PathBuf,
is_inspecting: bool, is_inspecting: bool,
is_repl: bool, is_repl: bool,
code_cache: Option<Arc<CodeCache>>, code_cache: Option<Arc<CodeCache>>,
@ -250,6 +252,7 @@ impl CliModuleLoaderFactory {
graph_kind: options.graph_kind(), graph_kind: options.graph_kind(),
lib_window: options.ts_type_lib_window(), lib_window: options.ts_type_lib_window(),
lib_worker: options.ts_type_lib_worker(), lib_worker: options.ts_type_lib_worker(),
initial_cwd: options.initial_cwd().to_path_buf(),
is_inspecting: options.is_inspecting(), is_inspecting: options.is_inspecting(),
is_repl: matches!( is_repl: matches!(
options.sub_command(), options.sub_command(),
@ -425,16 +428,44 @@ impl<TGraphContainer: ModuleGraphContainer>
&self, &self,
referrer: &str, referrer: &str,
) -> Result<ModuleSpecifier, AnyError> { ) -> Result<ModuleSpecifier, AnyError> {
// TODO(bartlomieju): ideally we shouldn't need to call `current_dir()` on each // todo(https://github.com/denoland/deno_core/pull/741): use function from deno_core
// call - maybe it should be caller's responsibility to pass it as an arg? fn specifier_has_uri_scheme(specifier: &str) -> bool {
let cwd = std::env::current_dir().context("Unable to get CWD")?; let mut chars = specifier.chars();
if referrer.is_empty() && self.shared.is_repl { let mut len = 0usize;
// The first character must be a letter.
match chars.next() {
Some(c) if c.is_ascii_alphabetic() => len += 1,
_ => return false,
}
// Second and following characters must be either a letter, number,
// plus sign, minus sign, or dot.
loop {
match chars.next() {
Some(c) if c.is_ascii_alphanumeric() || "+-.".contains(c) => len += 1,
Some(':') if len >= 2 => return true,
_ => return false,
}
}
}
let referrer = if referrer.is_empty() && self.shared.is_repl {
// FIXME(bartlomieju): this is a hacky way to provide compatibility with REPL // FIXME(bartlomieju): this is a hacky way to provide compatibility with REPL
// and `Deno.core.evalContext` API. Ideally we should always have a referrer filled // and `Deno.core.evalContext` API. Ideally we should always have a referrer filled
// but sadly that's not the case due to missing APIs in V8. "./$deno$repl.ts"
deno_core::resolve_path("./$deno$repl.ts", &cwd).map_err(|e| e.into())
} else { } else {
deno_core::resolve_url_or_path(referrer, &cwd).map_err(|e| e.into()) referrer
};
if specifier_has_uri_scheme(referrer) {
deno_core::resolve_url(referrer).map_err(|e| e.into())
} else if referrer == "." {
// main module, use the initial cwd
deno_core::resolve_path(referrer, &self.shared.initial_cwd)
.map_err(|e| e.into())
} else {
// this cwd check is slow, so try to avoid it
let cwd = std::env::current_dir().context("Unable to get CWD")?;
deno_core::resolve_path(referrer, &cwd).map_err(|e| e.into())
} }
} }