From a7d8ce28cd6d0c4ef84ae0839ab3f10e82ebc3e2 Mon Sep 17 00:00:00 2001 From: luisopine Date: Wed, 2 Sep 2026 19:45:50 +0000 Subject: [PATCH] perf(client-generator-ts,client-generator-js): read the search queue by index instead of shift() `GenericArgsInfo.typeNeedsGenericModelArg` runs a breadth-first search over the input types reachable from a type and consumed its queue with `Array.prototype.shift()`. On a schema with a few hundred models the search from a create input visits most of the nested create inputs, and the queue grows to more than a hundred thousand items; V8's `shift()` is linear in the array length at that size, so the search is quadratic in its own queue. A CPU profile of `prisma generate` on a 316-model schema put 241 s of 272 s in that loop. Reading the queue through an index keeps the same order and the same visits. Generator time on the released 7.9.1 CLI with this change applied to its bundle, generated output byte-identical: 316-model schema (37k input types) 165 s -> 6 s odoo.prisma fixture (168 models) 73 s -> 3.6 s synthetic, N models x 4 relations each: 100 models x 4 relations 2.1 s -> 0.9 s 200 models x 4 relations 8.0 s -> 2.0 s 300 models x 4 relations 18.4 s -> 3.1 s 500 models x 4 relations 55.0 s -> 5.6 s 300 models x 8 relations 113.7 s -> 6.3 s Both generator packages carry the same file; both get the same change. The existing tests and the generation snapshot tests pass unchanged. Signed-off-by: luisopine Co-Authored-By: Claude Fable 5.1 --- packages/client-generator-js/src/GenericsArgsInfo.ts | 4 +++- packages/client-generator-ts/src/GenericsArgsInfo.ts | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/client-generator-js/src/GenericsArgsInfo.ts b/packages/client-generator-js/src/GenericsArgsInfo.ts index f52417fcf76a..4518bd31dccf 100644 --- a/packages/client-generator-js/src/GenericsArgsInfo.ts +++ b/packages/client-generator-js/src/GenericsArgsInfo.ts @@ -26,7 +26,9 @@ export class GenericArgsInfo { const toVisit: ToVisitItem[] = [{ type: topLevelType }] const visited = new Set() let item: ToVisitItem | undefined - while ((item = toVisit.shift())) { + // read the queue by index: it grows to hundreds of thousands of items and `shift()` is linear in its length + let head = 0 + while ((item = toVisit[head++])) { const { type: currentType } = item const cached = this._cache.get(currentType) if (cached === true) { diff --git a/packages/client-generator-ts/src/GenericsArgsInfo.ts b/packages/client-generator-ts/src/GenericsArgsInfo.ts index f52417fcf76a..4518bd31dccf 100644 --- a/packages/client-generator-ts/src/GenericsArgsInfo.ts +++ b/packages/client-generator-ts/src/GenericsArgsInfo.ts @@ -26,7 +26,9 @@ export class GenericArgsInfo { const toVisit: ToVisitItem[] = [{ type: topLevelType }] const visited = new Set() let item: ToVisitItem | undefined - while ((item = toVisit.shift())) { + // read the queue by index: it grows to hundreds of thousands of items and `shift()` is linear in its length + let head = 0 + while ((item = toVisit[head++])) { const { type: currentType } = item const cached = this._cache.get(currentType) if (cached === true) {