perf: optimize selection-set serializer hot path + fix extensions.http leak#4403
perf: optimize selection-set serializer hot path + fix extensions.http leak#4403Copilot wants to merge 10 commits into
Conversation
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
Apollo Federation Subgraph Compatibility Results
Learn more: |
💻 Website PreviewThe latest changes are available as preview in: https://670b87e1.envelop.pages.dev |
💻 Website PreviewThe latest changes are available as preview in: https://pr-4403.graphql-yoga.pages.dev |
✅ Yoga Benchmark Results |
💻 Website PreviewThe latest changes are available as preview in: https://4e59fee2.envelop.pages.dev |
💻 Website PreviewThe latest changes are available as preview in: https://pr-4403.graphql-yoga.pages.dev |
💻 Website PreviewThe latest changes are available as preview in: https://4b84e5e6.envelop.pages.dev |
💻 Website PreviewThe latest changes are available as preview in: https://pr-4403.graphql-yoga.pages.dev |
💻 Website PreviewThe latest changes are available as preview in: https://5a9d897e.envelop.pages.dev |
💻 Website PreviewThe latest changes are available as preview in: https://1479a867.envelop.pages.dev |
💻 Website PreviewThe latest changes are available as preview in: https://pr-4403.graphql-yoga.pages.dev |
…ults Co-authored-by: ardatan <20847995+ardatan@users.noreply.github.com>
…e unused QUOTE import) Co-authored-by: ardatan <20847995+ardatan@users.noreply.github.com>
…gnore Co-authored-by: ardatan <20847995+ardatan@users.noreply.github.com>
…serialization Co-authored-by: ardatan <20847995+ardatan@users.noreply.github.com>
- Fast-path stringifyString: scan for special chars, skip JSON.stringify for plain strings - Add scalarHint to ProjectionPlanField for type-specific leaf serialization (String/Int/Float/Boolean/ID) - Pre-compute hasSkip/hasInclude booleans on each plan field to avoid .length > 0 checks in hot loop - Lazy __typename lookup in projectObject: only pay for property access when type guards or __typename output exists - projectEnumValue: use direct quote-wrapping for validated enum identifiers (no JSON.stringify needed) Co-authored-by: ardatan <20847995+ardatan@users.noreply.github.com>
Co-authored-by: ardatan <20847995+ardatan@users.noreply.github.com>
…ey fragments, use indexed loops Co-authored-by: ardatan <20847995+ardatan@users.noreply.github.com>
…ethods Co-authored-by: ardatan <20847995+ardatan@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
415bfcb to
596129d
Compare
💻 Website PreviewThe latest changes are available as preview in: https://7afc0398.envelop.pages.dev |
💻 Website PreviewThe latest changes are available as preview in: https://pr-4403.graphql-yoga.pages.dev |
…ization + fix extensions.http leak Co-authored-by: ardatan <20847995+ardatan@users.noreply.github.com> Agent-Logs-Url: https://github.com/graphql-hive/graphql-yoga/sessions/cabef9b6-6cba-4aea-a8ac-033860eac2c7
💻 Website PreviewThe latest changes are available as preview in: https://8f5d0508.envelop.pages.dev |
💻 Website PreviewThe latest changes are available as preview in: https://pr-4403.graphql-yoga.pages.dev |
Benchmark comparison showed the selection-set serialization branch running ~5-6% slower than
main(360µs vs 348µs avg; 332k vs 351k iterations/2.5min). Also identified a correctness bug where the internalextensions.httpfield was leaking to clients through the new fast path.Correctness
Strip
extensions.httpinstringifyWithDocument— the fast path bypassedomitInternalsFromResultErrors, so Yoga's internal HTTP status hints (extensions.http) were included in the serialized response. Now uses a sharedRESULT_EXTENSIONS_OPTIONSwithignoredFieldsto strip internal fields, and skips the"extensions"key entirely when only internal fields are present (avoids emitting"extensions":{}).Performance
commaEscapedKey— pre-compute',' + escapedKeyat plan compile time. The hot loop now usesfield.commaEscapedKeyfor non-first fields, eliminating one string concatenation per non-first field (~240 ops saved per benchmark request).isSimpleflag onProjectionPlanField— pre-computed astypeGuard === null && !hasSkip && !hasInclude && !isTypename. When true, the serializer skips four branch checks per field and jumps directly to value serialization. For the benchmark query where every field is simple, this eliminates 4 × 260 = 1,040 branches per request.hasConditionalFieldsonCompiledProjectionPlan— recursively pre-computed at plan compile time.getVariableValuesis now gated onplan.hasConditionalFields && plan.variableDefinitions.length > 0. Queries that declare variables but use no@skip/@include(e.g. pagination) skip coercion entirely.✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.