From 2cb67d7294cd0c1ff399e7ca4e4f6bfbde973bfa Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Tue, 7 May 2024 13:37:47 +0200 Subject: [PATCH] fix: out-of-memory error during peers resolution (#8058) --- .changeset/kind-radios-admire.md | 6 +++ .../resolve-dependencies/src/resolvePeers.ts | 54 +++++++++++-------- 2 files changed, 39 insertions(+), 21 deletions(-) create mode 100644 .changeset/kind-radios-admire.md diff --git a/.changeset/kind-radios-admire.md b/.changeset/kind-radios-admire.md new file mode 100644 index 00000000000..3e99b37eb57 --- /dev/null +++ b/.changeset/kind-radios-admire.md @@ -0,0 +1,6 @@ +--- +"@pnpm/resolve-dependencies": patch +"pnpm": patch +--- + +Improve the performance of the peers resolution stage by utilizing more cache [#8058](https://github.com/pnpm/pnpm/pull/8058). diff --git a/pkg-manager/resolve-dependencies/src/resolvePeers.ts b/pkg-manager/resolve-dependencies/src/resolvePeers.ts index d65822d4023..774062b45f1 100644 --- a/pkg-manager/resolve-dependencies/src/resolvePeers.ts +++ b/pkg-manager/resolve-dependencies/src/resolvePeers.ts @@ -350,28 +350,40 @@ async function resolvePeersOfNode ( })) ) ) - const hit = ctx.peersCache.get(resolvedPackage.depPath)?.find((cache) => { - for (const [name, cachedNodeId] of cache.resolvedPeers) { - const parentPkgNodeId = parentPkgs[name]?.nodeId - if (!parentPkgNodeId || !cachedNodeId) return false - if (parentPkgNodeId === cachedNodeId) continue - if ( - ctx.pathsByNodeId.has(cachedNodeId) && - ctx.pathsByNodeId.get(cachedNodeId) === ctx.pathsByNodeId.get(parentPkgNodeId) - ) continue - if (!ctx.dependenciesTree.has(parentPkgNodeId) && parentPkgNodeId.startsWith('link:')) { - return false + const hit = findHit(resolvedPackage.depPath) + function findHit (depPath: string, pendingCacheSearches: string[] = []) { + const cacheItems = ctx.peersCache.get(depPath) + if (!cacheItems) return undefined + const newPendingCacheSearches = [...pendingCacheSearches, depPath] + return cacheItems.find((cache) => { + for (const [name, cachedNodeId] of cache.resolvedPeers) { + const parentPkgNodeId = parentPkgs[name]?.nodeId + if (!parentPkgNodeId || !cachedNodeId) return false + if (parentPkgNodeId === cachedNodeId) continue + if ( + ctx.pathsByNodeId.has(cachedNodeId) && + ctx.pathsByNodeId.get(cachedNodeId) === ctx.pathsByNodeId.get(parentPkgNodeId) + ) continue + if (!ctx.dependenciesTree.has(parentPkgNodeId) && parentPkgNodeId.startsWith('link:')) { + return false + } + const parentDepPath = (ctx.dependenciesTree.get(parentPkgNodeId)!.resolvedPackage as T).depPath + if (!ctx.purePkgs.has(parentDepPath)) { + if ( + newPendingCacheSearches.includes(parentDepPath) || + findHit(parentDepPath, newPendingCacheSearches) + ) continue + return false + } + const cachedDepPath = (ctx.dependenciesTree.get(cachedNodeId)!.resolvedPackage as T).depPath + if (parentDepPath !== cachedDepPath) return false } - const parentDepPath = (ctx.dependenciesTree.get(parentPkgNodeId)!.resolvedPackage as T).depPath - if (!ctx.purePkgs.has(parentDepPath)) return false - const cachedDepPath = (ctx.dependenciesTree.get(cachedNodeId)!.resolvedPackage as T).depPath - if (parentDepPath !== cachedDepPath) return false - } - for (const missingPeer of cache.missingPeers) { - if (parentPkgs[missingPeer]) return false - } - return true - }) + for (const missingPeer of cache.missingPeers) { + if (parentPkgs[missingPeer]) return false + } + return true + }) + } if (hit != null) { return { missingPeers: hit.missingPeers,