Skip to content

[Fusion] Write forwarded variables once per fetch - #10524

Open
tobias-tengler wants to merge 5 commits into
mainfrom
tte/fusion-write-forwarded-variables-once
Open

tobias-tengler wants to merge 5 commits into
mainfrom
tte/fusion-write-forwarded-variables-once

Conversation

@tobias-tengler

@tobias-tengler tobias-tengler commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

When the gateway resolves an entity lookup, FetchResultStore builds one set of variables per parent entity. Every set repeated the variables forwarded from the request, so the forwarded values were serialized from their syntax nodes again for each entity, including escaping strings and formatting numbers.

This PR writes the forwarded variables once per fetch and copies their bytes into each entity's variables through a new internal JsonWriter.WriteRawProperties. A fetch for a single entity still writes them directly, because there is nothing to reuse. The buffer stays on the pooled store and is released when a large input makes it grow beyond 16 KB.

Benchmarks

Entities Forwarded variables Version Mean Ratio Allocated Alloc Ratio
1 None main 165.5 ns 1.00 64 B 1.00
1 None PR 170.6 ns 1.03 64 B 1.00
1 Few main 226.9 ns 1.00 64 B 1.00
1 Few PR 221.6 ns 0.98 64 B 1.00
1 Many main 588.0 ns 1.00 192 B 1.00
1 Many PR 595.2 ns 1.01 192 B 1.00
25 None main 2.912 μs 1.00 1.06 KB 1.00
25 None PR 2.530 μs 0.87 1.06 KB 1.00
25 Few main 4.146 μs 1.00 1.06 KB 1.00
25 Few PR 3.586 μs 0.86 1.06 KB 1.00
25 Many main 13.17 μs 1.00 2.63 KB 1.00
25 Many PR 5.810 μs 0.44 1.13 KB 0.43
100 None main 11.83 μs 1.00 3.99 KB 1.00
100 None PR 12.10 μs 1.02 3.99 KB 1.00
100 Few main 17.90 μs 1.00 3.99 KB 1.00
100 Few PR 15.31 μs 0.86 3.99 KB 1.00
100 Many main 54.84 μs 1.00 10.24 KB 1.00
100 Many PR 21.65 μs 0.39 4.05 KB 0.40

This is a net improvement. A lookup of 25 or 100 entities that forwards several variables is 2.3x to 2.5x faster and allocates 60% less, and with a single forwarded variable it is 14% faster, because the forwarded variables are serialized once per fetch instead of once per entity. A lookup of a single entity keeps the direct write and is within noise of main. The None cases do not touch the changed code, and their differences are run-to-run noise, which is wide for the 25 and 100 entity cases. The costs are one 4 KB pooled buffer per store and one more write path in FetchResultStore, which are small next to the gain on exactly the fetch shape that batching produces.

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Patch coverage

100.0% of changed lines covered (59/59)

File Covered Changed Patch %
…/Execution/Results/FetchResultStore.Pooling.cs 5 5 100.0% 🟢
…/src/Fusion.Execution/Execution/Results/FetchResultStore.cs 35 35 100.0% 🟢
src/HotChocolate/Json/src/Json/JsonWriter.cs 19 19 100.0% 🟢

Project coverage: 58.6% (314332/536516 lines)

Variable value sets for entity fetches wrote every forwarded variable again
for each entity. The forwarded variables are now written once per fetch and
their bytes are copied into each entity's variables, while a single entity
still writes them directly.
Serialize the forwarded variables once per fetch and splice the bytes into
every entity when a fetch has more than one entity. A single entity still
writes them directly. The scratch buffer is an eager field that is trimmed
like the other buffers, and the raw property write ignores an empty span and
asserts its contract.
@tobias-tengler
tobias-tengler force-pushed the tte/fusion-write-forwarded-variables-once branch from e8dd999 to 1294822 Compare October 9, 2026 16:19
The buffer is only rented when a fetch with more than one entity forwards
variables, and it is released again when a large input made it grow.
@tobias-tengler
tobias-tengler marked this pull request as ready for review October 9, 2026 16:34
Copilot AI balanced review requested due to automatic review settings October 9, 2026 16:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The optimization preserves existing output semantics, handles pooling lifecycle correctly, and has focused coverage for affected paths.

0 open findings

What changed in this PR

Optimizes Fusion entity fetches by serializing forwarded variables once and reusing their JSON bytes across entities.

Changes:

  • Adds raw JSON property writing support.
  • Reuses a pooled forwarded-variable buffer with size-based cleanup.
  • Adds coverage for separators, entity batching, failures, and snapshots.
File Description
JsonWriterTests.cs Tests raw property writing behavior.
JsonWriter.cs Adds WriteRawProperties.
HotChocolate.Text.Json.csproj Exposes internals to JSON tests.
FetchResultStoreTests.cs Tests forwarded-variable reuse paths.
FetchResultStore.Pooling.cs Releases oversized reusable buffers.
FetchResultStore.cs Serializes forwarded variables once per multi-entity fetch.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants