0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 17:34:47 -05:00

perf: cache node resolution when accesing a global (#19930)

Reclaims some of the performance hit introduced by
https://github.com/denoland/deno/pull/19307.
This commit is contained in:
Bartek Iwańczuk 2023-07-25 23:43:00 +02:00 committed by GitHub
parent 5d8d1105a4
commit 06209f824c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 86 additions and 9 deletions

View file

@ -1,9 +1,6 @@
[WILDCARD]package.json file found at '[WILDCARD]with_package_json[WILDCARD]npm_binary[WILDCARD]package.json'
[WILDCARD]
this
[WILDCARD]
is
[WILDCARD]
a
[WILDCARD]
test

View file

@ -5,10 +5,42 @@ pub use inner::*;
#[cfg(feature = "sync_fs")]
mod inner {
#![allow(clippy::disallowed_types)]
use std::ops::Deref;
use std::ops::DerefMut;
pub use std::sync::Arc as MaybeArc;
pub use core::marker::Send as MaybeSend;
pub use core::marker::Sync as MaybeSync;
pub struct MaybeArcMutexGuard<'lock, T>(std::sync::MutexGuard<'lock, T>);
impl<'lock, T> Deref for MaybeArcMutexGuard<'lock, T> {
type Target = std::sync::MutexGuard<'lock, T>;
fn deref(&self) -> &std::sync::MutexGuard<'lock, T> {
&self.0
}
}
impl<'lock, T> DerefMut for MaybeArcMutexGuard<'lock, T> {
fn deref_mut(&mut self) -> &mut std::sync::MutexGuard<'lock, T> {
&mut self.0
}
}
#[derive(Debug)]
pub struct MaybeArcMutex<T>(std::sync::Arc<std::sync::Mutex<T>>);
impl<T> MaybeArcMutex<T> {
pub fn new(val: T) -> Self {
Self(std::sync::Arc::new(std::sync::Mutex::new(val)))
}
}
impl<'lock, T> MaybeArcMutex<T> {
pub fn lock(&'lock self) -> MaybeArcMutexGuard<'lock, T> {
MaybeArcMutexGuard(self.0.lock().unwrap())
}
}
}
#[cfg(not(feature = "sync_fs"))]
@ -19,4 +51,33 @@ mod inner {
impl<T> MaybeSync for T where T: ?Sized {}
pub trait MaybeSend {}
impl<T> MaybeSend for T where T: ?Sized {}
pub struct MaybeArcMutexGuard<'lock, T>(std::cell::RefMut<'lock, T>);
impl<'lock, T> Deref for MaybeArcMutexGuard<'lock, T> {
type Target = std::cell::RefMut<'lock, T>;
fn deref(&self) -> &std::cell::RefMut<'lock, T> {
&self.0
}
}
impl<'lock, T> DerefMut for MaybeArcMutexGuard<'lock, T> {
fn deref_mut(&mut self) -> &mut std::cell::RefMut<'lock, T> {
&mut self.0
}
}
#[derive(Debug)]
pub struct MaybeArcMutex<T>(std::rc::Rc<std::cell::RefCell<T>>);
impl<T> MaybeArcMutex<T> {
pub fn new(val: T) -> Self {
Self(std::rc::Rc::new(std::cell::RefCell::new(val)))
}
}
impl<'lock, T> MaybeArcMutex<T> {
pub fn lock(&'lock self) -> MaybeArcMutexGuard<'lock, T> {
MaybeArcMutexGuard(self.0.borrow_mut())
}
}
}

View file

@ -267,16 +267,12 @@ fn current_mode(scope: &mut v8::HandleScope) -> Mode {
return Mode::Deno;
};
let string = v8_string.to_rust_string_lossy(scope);
// TODO: don't require parsing the specifier
let Ok(specifier) = deno_core::ModuleSpecifier::parse(&string) else {
return Mode::Deno;
};
let op_state = deno_core::JsRuntime::op_state_from(scope);
let op_state = op_state.borrow();
let Some(node_resolver) = op_state.try_borrow::<Rc<NodeResolver>>() else {
return Mode::Deno;
};
if node_resolver.in_npm_package(&specifier) {
if node_resolver.in_npm_package_with_cache(string) {
Mode::Node
} else {
Mode::Deno

View file

@ -1,5 +1,6 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use std::collections::HashMap;
use std::path::Path;
use std::path::PathBuf;
@ -111,17 +112,39 @@ pub type NodeResolverRc = deno_fs::sync::MaybeArc<NodeResolver>;
pub struct NodeResolver {
fs: FileSystemRc,
npm_resolver: NpmResolverRc,
in_npm_package_cache: deno_fs::sync::MaybeArcMutex<HashMap<String, bool>>,
}
impl NodeResolver {
pub fn new(fs: FileSystemRc, npm_resolver: NpmResolverRc) -> Self {
Self { fs, npm_resolver }
Self {
fs,
npm_resolver,
in_npm_package_cache: deno_fs::sync::MaybeArcMutex::new(HashMap::new()),
}
}
pub fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
self.npm_resolver.in_npm_package(specifier)
}
pub fn in_npm_package_with_cache(&self, specifier: String) -> bool {
let mut cache = self.in_npm_package_cache.lock();
if let Some(result) = cache.get(&specifier) {
return *result;
}
let result =
if let Ok(specifier) = deno_core::ModuleSpecifier::parse(&specifier) {
self.npm_resolver.in_npm_package(&specifier)
} else {
false
};
cache.insert(specifier, result);
result
}
/// This function is an implementation of `defaultResolve` in
/// `lib/internal/modules/esm/resolve.js` from Node.
pub fn resolve(