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

perf(npm): make dependency resolution faster (#16694)

This commit is contained in:
David Sherret 2022-11-17 21:50:43 -05:00 committed by GitHub
parent 409e6c8402
commit 5867a12920
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -139,6 +139,11 @@ struct Node {
pub parents: BTreeMap<String, BTreeSet<NodeParent>>, pub parents: BTreeMap<String, BTreeSet<NodeParent>>,
pub children: BTreeMap<String, NpmPackageId>, pub children: BTreeMap<String, NpmPackageId>,
pub deps: Arc<Vec<NpmDependencyEntry>>, pub deps: Arc<Vec<NpmDependencyEntry>>,
/// Whether the node has demonstrated to have no peer dependencies in its
/// descendants. If this is true then we can skip analyzing this node
/// again when we encounter it another time in the dependency tree, which
/// is much faster.
pub no_peers: bool,
} }
impl Node { impl Node {
@ -225,6 +230,7 @@ impl Graph {
parents: Default::default(), parents: Default::default(),
children: Default::default(), children: Default::default(),
deps: Default::default(), deps: Default::default(),
no_peers: false,
})); }));
self self
.packages_by_name .packages_by_name
@ -492,7 +498,7 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
package_info: &NpmPackageInfo, package_info: &NpmPackageInfo,
parent_id: &NpmPackageId, parent_id: &NpmPackageId,
visited_versions: &Arc<VisitedVersionsPath>, visited_versions: &Arc<VisitedVersionsPath>,
) -> Result<(), AnyError> { ) -> Result<Arc<Mutex<Node>>, AnyError> {
let node = self.resolve_node_from_info( let node = self.resolve_node_from_info(
&entry.name, &entry.name,
match entry.kind { match entry.kind {
@ -515,7 +521,7 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
&NodeParent::Node(parent_id.clone()), &NodeParent::Node(parent_id.clone()),
); );
self.try_add_pending_unresolved_node(Some(visited_versions), &node); self.try_add_pending_unresolved_node(Some(visited_versions), &node);
Ok(()) Ok(node)
} }
fn try_add_pending_unresolved_node( fn try_add_pending_unresolved_node(
@ -523,7 +529,13 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
maybe_previous_visited_versions: Option<&Arc<VisitedVersionsPath>>, maybe_previous_visited_versions: Option<&Arc<VisitedVersionsPath>>,
node: &Arc<Mutex<Node>>, node: &Arc<Mutex<Node>>,
) { ) {
let node_id = node.lock().id.clone(); let node_id = {
let node = node.lock();
if node.no_peers {
return; // skip, no need to analyze this again
}
node.id.clone()
};
let visited_versions = match maybe_previous_visited_versions { let visited_versions = match maybe_previous_visited_versions {
Some(previous_visited_versions) => { Some(previous_visited_versions) => {
match previous_visited_versions.with_id(&node_id) { match previous_visited_versions.with_id(&node_id) {
@ -576,6 +588,7 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
// so these are resolved in that order // so these are resolved in that order
deps.sort(); deps.sort();
node.deps = Arc::new(deps); node.deps = Arc::new(deps);
node.no_peers = node.deps.is_empty();
} }
Ok(node) Ok(node)
@ -589,8 +602,8 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
{ {
let (mut parent_id, deps, existing_children) = { let (mut parent_id, deps, existing_children) = {
let parent_node = parent_node.lock(); let parent_node = parent_node.lock();
if parent_node.forgotten { if parent_node.forgotten || parent_node.no_peers {
// todo(dsherret): we should try to reproduce this scenario and write a test // todo(dsherret): we should try to reproduce this forgotten scenario and write a test
continue; continue;
} }
@ -622,20 +635,25 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
} }
// resolve the dependencies // resolve the dependencies
let mut found_peer = false;
for dep in deps.iter() { for dep in deps.iter() {
let package_info = self.api.package_info(&dep.name).await?; let package_info = self.api.package_info(&dep.name).await?;
match dep.kind { match dep.kind {
NpmDependencyEntryKind::Dep => { NpmDependencyEntryKind::Dep => {
self.analyze_dependency( let node = self.analyze_dependency(
dep, dep,
&package_info, &package_info,
&parent_id, &parent_id,
&visited_versions, &visited_versions,
)?; )?;
if !found_peer {
found_peer = !node.lock().no_peers;
}
} }
NpmDependencyEntryKind::Peer NpmDependencyEntryKind::Peer
| NpmDependencyEntryKind::OptionalPeer => { | NpmDependencyEntryKind::OptionalPeer => {
found_peer = true;
let maybe_new_parent_id = self.resolve_peer_dep( let maybe_new_parent_id = self.resolve_peer_dep(
&dep.bare_specifier, &dep.bare_specifier,
&parent_id, &parent_id,
@ -654,6 +672,10 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
} }
} }
} }
if !found_peer {
self.graph.borrow_node(&parent_id).no_peers = true;
}
} }
} }
Ok(()) Ok(())