From 9d9456442f82d8be2c80e9725359825cbdb26be9 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Wed, 2 Sep 2020 16:47:18 +0300 Subject: [PATCH] perf: using pkgId as nodeId for leaf deps --- .changeset/mean-zoos-shout.md | 5 +++ .../resolve-dependencies/src/nodeIdUtils.ts | 1 + .../src/resolveDependencies.ts | 31 +++++++++++++------ 3 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 .changeset/mean-zoos-shout.md diff --git a/.changeset/mean-zoos-shout.md b/.changeset/mean-zoos-shout.md new file mode 100644 index 0000000000..076902da56 --- /dev/null +++ b/.changeset/mean-zoos-shout.md @@ -0,0 +1,5 @@ +--- +"@pnpm/resolve-dependencies": major +--- + +In case of leaf dependencies (dependencies that have no prod deps or peer deps), we only ever need to analyze one leaf dep in a graph, so the nodeId can be short and stateless, like the package ID. diff --git a/packages/resolve-dependencies/src/nodeIdUtils.ts b/packages/resolve-dependencies/src/nodeIdUtils.ts index a934181d74..7e451366ca 100644 --- a/packages/resolve-dependencies/src/nodeIdUtils.ts +++ b/packages/resolve-dependencies/src/nodeIdUtils.ts @@ -8,6 +8,7 @@ export function nodeIdContainsSequence (nodeId: string, pkgId1: string, pkgId2: } export function createNodeId (parentNodeId: string, pkgId: string) { + // using ">" as a separator because it will never be used inside a package ID return `${parentNodeId}${pkgId}>` } diff --git a/packages/resolve-dependencies/src/resolveDependencies.ts b/packages/resolve-dependencies/src/resolveDependencies.ts index 9fa510a91a..d5f8624632 100644 --- a/packages/resolve-dependencies/src/resolveDependencies.ts +++ b/packages/resolve-dependencies/src/resolveDependencies.ts @@ -677,8 +677,11 @@ async function resolveDependency ( }) } - // using colon as it will never be used inside a package ID - const nodeId = createNodeId(options.parentPkg.nodeId, pkgResponse.body.id) + // In case of leaf dependencies (dependencies that have no prod deps or peer deps), + // we only ever need to analyze one leaf dep in a graph, so the nodeId can be short and stateless. + const nodeId = pkgIsLeaf(pkg) + ? pkgResponse.body.id + : createNodeId(options.parentPkg.nodeId, pkgResponse.body.id) const currentIsInstallable = ( ctx.force || @@ -732,13 +735,17 @@ async function resolveDependency ( ctx.resolvedPackagesByPackageId[pkgResponse.body.id].dev = ctx.resolvedPackagesByPackageId[pkgResponse.body.id].dev || wantedDependency.dev ctx.resolvedPackagesByPackageId[pkgResponse.body.id].optional = ctx.resolvedPackagesByPackageId[pkgResponse.body.id].optional && wantedDependency.optional - ctx.pendingNodes.push({ - alias: wantedDependency.alias || pkg.name, - depth: options.currentDepth, - installable, - nodeId, - resolvedPackage: ctx.resolvedPackagesByPackageId[pkgResponse.body.id], - }) + if (ctx.dependenciesTree[nodeId]) { + ctx.dependenciesTree[nodeId].depth = Math.min(ctx.dependenciesTree[nodeId].depth, options.currentDepth) + } else { + ctx.pendingNodes.push({ + alias: wantedDependency.alias || pkg.name, + depth: options.currentDepth, + installable, + nodeId, + resolvedPackage: ctx.resolvedPackagesByPackageId[pkgResponse.body.id], + }) + } } return { @@ -758,6 +765,12 @@ async function resolveDependency ( } } +function pkgIsLeaf (pkg: PackageManifest) { + return R.isEmpty(pkg.dependencies ?? {}) && + R.isEmpty(pkg.optionalDependencies ?? {}) && + R.isEmpty(pkg.peerDependencies ?? {}) +} + function getResolvedPackage ( options: { dependencyLockfile?: PackageSnapshot