From 81d90c9dd259c11459a811069c0c03da88c0aefd Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Mon, 27 May 2024 00:54:34 +0200 Subject: [PATCH] fix: reduce memory usage by using numbers for Node IDs (#8135) --- .changeset/hot-seahorses-invite.md | 5 +++++ pkg-manager/resolve-dependencies/src/index.ts | 2 +- pkg-manager/resolve-dependencies/src/nextNodeId.ts | 4 ++-- .../resolve-dependencies/src/resolvePeers.ts | 14 +++++++------- .../test/dedupeDepPaths.test.ts | 2 +- 5 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 .changeset/hot-seahorses-invite.md diff --git a/.changeset/hot-seahorses-invite.md b/.changeset/hot-seahorses-invite.md new file mode 100644 index 0000000000..a069e9247b --- /dev/null +++ b/.changeset/hot-seahorses-invite.md @@ -0,0 +1,5 @@ +--- +"@pnpm/resolve-dependencies": patch +--- + +Reduce memory usage during peer dependency resolution by using numbers for Node IDs. diff --git a/pkg-manager/resolve-dependencies/src/index.ts b/pkg-manager/resolve-dependencies/src/index.ts index 395233f816..8fed36f1ef 100644 --- a/pkg-manager/resolve-dependencies/src/index.ts +++ b/pkg-manager/resolve-dependencies/src/index.ts @@ -170,7 +170,7 @@ export async function resolveDependencies ( const target = !opts.excludeLinksFromLockfile || isSubdir(opts.lockfileDir, linkedDependency.resolution.directory) ? linkedDependency.resolution.directory : path.join(project.modulesDir, linkedDependency.alias) - const linkedDir = createNodeIdForLinkedLocalPkg(opts.lockfileDir, target) + const linkedDir = createNodeIdForLinkedLocalPkg(opts.lockfileDir, target) as string topParents.push({ name: linkedDependency.alias, version: linkedDependency.version, diff --git a/pkg-manager/resolve-dependencies/src/nextNodeId.ts b/pkg-manager/resolve-dependencies/src/nextNodeId.ts index 66e83c3ab9..ec5993b21e 100644 --- a/pkg-manager/resolve-dependencies/src/nextNodeId.ts +++ b/pkg-manager/resolve-dependencies/src/nextNodeId.ts @@ -2,8 +2,8 @@ let nodeIdCounter = 0 type Brand = K & { __brand: T } -export type NodeId = Brand +export type NodeId = Brand export function nextNodeId (): NodeId { - return (++nodeIdCounter).toString() as NodeId + return ++nodeIdCounter as NodeId } diff --git a/pkg-manager/resolve-dependencies/src/resolvePeers.ts b/pkg-manager/resolve-dependencies/src/resolvePeers.ts index 52ceeab47c..2b4735ca2c 100644 --- a/pkg-manager/resolve-dependencies/src/resolvePeers.ts +++ b/pkg-manager/resolve-dependencies/src/resolvePeers.ts @@ -341,7 +341,7 @@ interface ResolvePeersContext { depPathsByPkgId?: Map> } -type CalculateDepPath = (cycles: string[][]) => Promise +type CalculateDepPath = (cycles: NodeId[][]) => Promise type FinishingResolutionPromise = Promise interface ParentPkgInfo { @@ -493,7 +493,7 @@ async function resolvePeersOfNode ( const peerIds: PeerId[] = [] const pendingPeerNodeIds: NodeId[] = [] for (const [alias, peerNodeId] of allResolvedPeers.entries()) { - if (peerNodeId.startsWith('link:')) { + if (typeof peerNodeId === 'string' && peerNodeId.startsWith('link:')) { const linkedDir = peerNodeId.slice(5) peerIds.push({ name: alias, @@ -526,7 +526,7 @@ async function resolvePeersOfNode ( async function calculateDepPath ( peerIds: PeerId[], pendingPeerNodeIds: NodeId[], - cycles: string[][] + cycles: NodeId[][] ): Promise { const cyclicPeerNodeIds = new Set() for (const cycle of cycles) { @@ -618,7 +618,7 @@ function findHit (ctx: { ctx.pathsByNodeId.has(cachedNodeId) && ctx.pathsByNodeId.get(cachedNodeId) === ctx.pathsByNodeId.get(parentPkgNodeId) ) continue - if (!ctx.dependenciesTree.has(parentPkgNodeId) && parentPkgNodeId.startsWith('link:')) { + if (!ctx.dependenciesTree.has(parentPkgNodeId) && typeof parentPkgNodeId === 'string' && parentPkgNodeId.startsWith('link:')) { return false } const parentPkgId = (ctx.dependenciesTree.get(parentPkgNodeId)!.resolvedPackage as T).pkgIdWithPatchHash @@ -756,7 +756,7 @@ async function resolvePeersOfChildren ( const parentDepPaths: Record = {} for (const [name, parentPkg] of Object.entries(parentPkgs)) { if (!ctx.allPeerDepNames.has(name)) continue - if (parentPkg.nodeId && !parentPkg.nodeId.startsWith('link:')) { + if (parentPkg.nodeId && (typeof parentPkg.nodeId === 'number' || !parentPkg.nodeId.startsWith('link:'))) { parentDepPaths[name] = { pkgIdWithPatchHash: (ctx.dependenciesTree.get(parentPkg.nodeId)!.resolvedPackage as T).pkgIdWithPatchHash, depth: parentPkg.depth, @@ -793,7 +793,7 @@ async function resolvePeersOfChildren ( } } if (calculateDepPaths.length) { - const { cycles } = analyzeGraph(graph as unknown as Graph) + const { cycles } = analyzeGraph(graph as unknown as Graph) as unknown as { cycles: NodeId[][] } finishingList.push(...calculateDepPaths.map((calculateDepPath) => calculateDepPath(cycles))) } const finishing = Promise.all(finishingList).then(() => {}) @@ -812,7 +812,7 @@ function _resolvePeers ( ctx: { currentDepth: number lockfileDir: string - nodeId: string + nodeId: NodeId parentPkgs: ParentRefs parentNodeIds: NodeId[] resolvedPackage: T diff --git a/pkg-manager/resolve-dependencies/test/dedupeDepPaths.test.ts b/pkg-manager/resolve-dependencies/test/dedupeDepPaths.test.ts index 50c4449bbe..0413f54a6e 100644 --- a/pkg-manager/resolve-dependencies/test/dedupeDepPaths.test.ts +++ b/pkg-manager/resolve-dependencies/test/dedupeDepPaths.test.ts @@ -91,7 +91,7 @@ test('packages are not deduplicated when versions do not match', async () => { ['>project4>bar/2.0.0>' as NodeId, peers.bar_2_0_0], ['>project4>baz/2.0.0>' as NodeId, peers.baz_2_0_0], - ] satisfies Array<[string, PartialResolvedPackage]>).map(([path, resolvedPackage]) => [path, { + ] satisfies Array<[NodeId, PartialResolvedPackage]>).map(([path, resolvedPackage]) => [path, { children: {}, installable: {}, resolvedPackage,