perf(import): memoize print() in processImport (O(n²) → O(n) on large schemas)#8258
perf(import): memoize print() in processImport (O(n²) → O(n) on large schemas)#8258lemonmade wants to merge 1 commit into
Conversation
processImport de-duplicates collected definitions by printing each to SDL and comparing strings. A single definition node appears in many dependency sets (any widely-referenced type is pulled in by every dependent), so print() ran ~O(n^2) times for n unique nodes. For large, densely-connected schemas this print/visit work dominates import time. Memoize print() by node identity so each unique node prints at most once. print() is pure, so output is identical (the existing 80 import tests pass). On a ~12k-line schema imported across three projects, a downstream codegen pass dropped from ~133s to ~17s. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 3627e4c The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds a ChangesMemoize print in processImport
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Problem
processImportde-duplicates the collected definitions by printing each one to SDL and comparing the strings:A single definition node appears in many of the dependency sets in
set— any widely-referenced type (a rootQuery, a sharedNode/User, etc.) is pulled into the dependency set of every definition that depends on it. Soprint()is called roughly O(n²) times fornunique nodes.Because
print(ast)in graphql-js is implemented asvisit(ast, printDocASTReducer), this is a full AST walk each time, and on large, densely-connected schemas it dominates import time.Profile (real-world schema)
A downstream codegen pass over a ~12,000-line schema imported across three projects spent ~133s, of which CPU profiling attributed ~63% to graphql-js
visit+ ~13% toprint— i.e. almost all of it to this oneprint(def)line. The tool's own type generation was ~0%.Fix
Memoize
printby node identity, so each unique node is printed at most once:printis a pure function of its node, so the de-duplication is byte-for-byte identical — this is a pure performance change.Result
@graphql-tools/importtests pass unchanged.Notes
patchchangeset included.Mapidentity keys are exact.🤖 Generated with Claude Code