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 children: BTreeMap<String, NpmPackageId>,
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 {
@ -225,6 +230,7 @@ impl Graph {
parents: Default::default(),
children: Default::default(),
deps: Default::default(),
no_peers: false,
}));
self
.packages_by_name
@ -492,7 +498,7 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
package_info: &NpmPackageInfo,
parent_id: &NpmPackageId,
visited_versions: &Arc<VisitedVersionsPath>,
) -> Result<(), AnyError> {
) -> Result<Arc<Mutex<Node>>, AnyError> {
let node = self.resolve_node_from_info(
&entry.name,
match entry.kind {
@ -515,7 +521,7 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
&NodeParent::Node(parent_id.clone()),
);
self.try_add_pending_unresolved_node(Some(visited_versions), &node);
Ok(())
Ok(node)
}
fn try_add_pending_unresolved_node(
@ -523,7 +529,13 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
maybe_previous_visited_versions: Option<&Arc<VisitedVersionsPath>>,
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 {
Some(previous_visited_versions) => {
match previous_visited_versions.with_id(&node_id) {
@ -576,6 +588,7 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
// so these are resolved in that order
deps.sort();
node.deps = Arc::new(deps);
node.no_peers = node.deps.is_empty();
}
Ok(node)
@ -589,8 +602,8 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
{
let (mut parent_id, deps, existing_children) = {
let parent_node = parent_node.lock();
if parent_node.forgotten {
// todo(dsherret): we should try to reproduce this scenario and write a test
if parent_node.forgotten || parent_node.no_peers {
// todo(dsherret): we should try to reproduce this forgotten scenario and write a test
continue;
}
@ -622,20 +635,25 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
}
// resolve the dependencies
let mut found_peer = false;
for dep in deps.iter() {
let package_info = self.api.package_info(&dep.name).await?;
match dep.kind {
NpmDependencyEntryKind::Dep => {
self.analyze_dependency(
let node = self.analyze_dependency(
dep,
&package_info,
&parent_id,
&visited_versions,
)?;
if !found_peer {
found_peer = !node.lock().no_peers;
}
}
NpmDependencyEntryKind::Peer
| NpmDependencyEntryKind::OptionalPeer => {
found_peer = true;
let maybe_new_parent_id = self.resolve_peer_dep(
&dep.bare_specifier,
&parent_id,
@ -654,6 +672,10 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
}
}
}
if !found_peer {
self.graph.borrow_node(&parent_id).no_peers = true;
}
}
}
Ok(())