Repository navigation
perf(executor): allocate scalar list paths only when needed - #8618
Conversation
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Defer indexed paths for leaf items packages/executor/src/execution/execute.ts, packages/executor/src/execution/__tests__/scalar-list-paths-test.ts, packages/executor/src/execution/__benchmarks__/executor.bench.ts, .changeset/lazy-scalar-list-item-paths.md |
Eligible synchronous, non-null, non-Error leaf items are serialized without first creating indexed paths. Error handling retains item paths, while streamed lists and other item types keep their existing path behavior. Tests cover serialization, error bubbling, iterator closure, nullish and promised items, and thenable getter access. A dense Float list benchmark and patch changeset are added. |
Babel template lifecycle
| Layer / File(s) | Summary |
|---|---|
Capture origin stacks and test template retention patches/@babel+template+8.0.0.patch, scripts/test-babel-template-retention.mjs, package.json, .github/workflows/tests.yml |
The Babel patch appends an origin stack only when capture returns a string. New tests check garbage collection, builder usability, template errors, custom stack formatters, and preservation of substitution errors. The package script and workflow run these tests. |
Priority:
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Refactor
Possibly related issues
- ardatan/graphql-tools#8616: This pull request implements the described indexed-path optimization for successful synchronous scalar and enum list items.
- ardatan/graphql-tools#8619: The Babel patch and retention tests address the described template-origin stack retention during leak checks.
Possibly related PRs
- ardatan/graphql-tools#8617: This PR changes the same executor list-completion implementation and benchmark, and its result compaction uses the completion output changed here.
- ardatan/graphql-tools#8621: This PR contains the same Babel patch, lifecycle script, workflow step, and retention tests.
Suggested reviewers: ardatan
Merge Risk: 
Minimal · up to 73436
-
No actionable regression is established by the reviewed changes; the PR is mergeable after normal checks.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passed-
Full details: Description check
-
Explanation
The pull request description directly explains the scalar and enum list path-allocation optimization, affected behavior, tests, benchmarks, CI remediation, and compatibility scope. It matches the changeset.
-
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 7 functions across 4 files. (3 skipped: 3 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches
-
🧪 Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
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.
A rabbit checks each list item’s place
And leaves no path for success to trace
It guards the errors as they appear
While template stacks stay clear
Then bounds through tests with whiskers bright
Comment @coderabbitai help to get the list of available commands.
🦋 Changeset detectedLatest commit: 73436ed The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
ardatan
left a comment
There was a problem hiding this comment.
Thanks for the careful leaf fast path and the characterization tests. Behavior looks aligned with the existing completeListItemValue path for the cases that matter (null / Error / Promise items, NonNull bubbling, async serialize, @stream left on the slow path).
Two asks before merge:
- Structure: the success path currently duplicates the error / async handling from
completeListItemValue. Could we keep a single completion path and allocate the indexed item path lazily (only when error or async completion needs it)? That would avoid drift between the two copies over time. - Benchmarks: we already have a Vitest bench suite for the executor (
packages/executor/src/execution/__benchmarks__/executor.bench.ts, vianpm run test:bench, compared against master in CI). Prefer extending that over the standalonescalar-list-paths.mjs, so the new case stays in the shared compare flow.
Not blocking on correctness from what I can see; happy to re-review after the cleanup / bench move.
|
The shared completion path and benchmark revisions are implemented in cde9563, following your review. The shared CI leak failure is addressed separately in #8621 and included here in 73436ed. Changes
Performance evidenceTwo million synchronous Float values, Node 24.15.0 / Linux ARM64 / GraphQL 17.0.2:
Fresh measurements use five alternating paired processes with matching serialized hashes. Vitest uses separate current/base runs. These are workload-specific observations, not general gateway latency claims. Local validation
CI remediationBabel cached a template builder retaining a raw origin Error and its V8 call-site receivers, including a calling Jest VM. The existing The companion's four Node 22/24 × GraphQL 16/17 CI jobs pass, including the existing leak checks. After applying that isolated development-tooling fix here, a fresh build and 1,765 tests pass locally. All exact-head checks pass on Both leak detectors, retries, timeouts, existing skips and suppression rules remain unchanged. Baseline evidence and its limitsThe same custom-loader leak signature appears on unchanged master CI. A local Node 22.23.3 / GraphQL 17 comparison also reproduced it on unchanged base and revised list head. That local comparison used the list branch, not an exact reproduction of this scalar CI runner. The minimal reproduction requires only a fresh module exporting NextPlease re-review the shared completion path. This PR remains independent on master, with sequential landing and merge coordination for the shared source/benchmark edits. |
ardatan
left a comment
There was a problem hiding this comment.
Thanks for the revision. The shared completion path and Vitest bench look good, and the CI compare shows a clear win on the dense scalar-list cases. Merging.
Description
Completing a synchronous scalar/enum list currently allocates an indexed path object for every successful item, even though scalar serialization receives no indexed resolve info. Resolve the nullable leaf type once and create a stable indexed path only for failures or asynchronous completion.
The same serializer still runs once per item.
completeListItemValueowns one shared completion/error/async pipeline; it materializes the indexed path only when fallback completion, errors or async work require it. Nulls, Errors, promised inputs, composite types, active streams and async iterators retain their existing behavior. Tests cover custom coercion and its ordering, nullable error indexes, asynchronous serialization/rejections, non-null bubbling, iterator cleanup and thenable getter reads.Related #8616.
Type of change
@graphql-tools/executor.How Has This Been Tested?
npm run ts:checkand changed-source ESLint pass.execution/__benchmarks__/executor.bench.tsVitest suite and CI comparison flow. Earlier standalone timing numbers described the pre-review implementation and have been removed; revised measurements are reported with their own validation evidence.Reproduce after building:
Use
BENCH_PACKAGE_ROOTto point the same suite at a separately built baseline checkout, as CI does. Test environment: Node 24.15.0, Linux ARM64, GraphQL 17.0.2. Local full-suite browser tests used Chromium and IPv4-first DNS for localhost servers.CI remediation
The shared baseline leak failure was traced to Babel's cached template builder retaining a raw origin Error and V8 call-site receivers, including the calling Jest VM. The independent fix #8621, included here, uses the existing
patch-packagepostinstall to retain only a formatted origin-stack string. Seven lifecycle/diagnostic checks cover collection, explicit-retention controls, usable builders and custom stack formatting. No detectors, retries, timeouts or existing suppression rules changed. All four Node22/24 × GraphQL16/17 CI jobs pass on the companion; this branch's new exact-head run is assessed separately. The final local build and all 1,765 ordinary tests pass with the patch applied.Exact head
73436ed942dd36cc154d51b6a7f5ed28ac6ba410: CI run 40588414792 passes all four Node22/24 × GraphQL16/17 jobs, including leak checks, along with build/types/lint and Bun. CodeQL, analysis and benchmark comparison also pass.Compatibility and discussion
Targets the active
masterline, currently executor 4.1.6, and requires no new dependency or engine version. It is independent of the completed-list storage patch, although both touchcompleteListValueand should be integrated with normal merge coordination.The maintainer confirmed that older executor majors do not receive maintained backport releases. Supported upstream adoption uses the current executor through Yoga 6 and matching Hive versions. Yoga 5's executor 1.x range does not receive this mainline change.
The older 1.5.7 source reference is unofficial and preserves the initial proposal, not these subsequent review revisions. It is not a released package, supported maintenance line or recommendation for production replacement. Do not force executor 4.x underneath Yoga 5.
Checklist
Developed and validated with Codex (GPT-6.1); the included reproduction supplies the performance evidence.