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:
parent
409e6c8402
commit
5867a12920
1 changed files with 28 additions and 6 deletions
|
@ -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(())
|
||||
|
|
Loading…
Reference in a new issue