Repository navigation
[Fusion] Write forwarded variables once per fetch - #10524
Open
tobias-tengler wants to merge 5 commits into
Open
tobias-tengler wants to merge 5 commits into
tobias-tengler wants to merge 5 commits into
Conversation
Contributor
Patch coverage100.0% of changed lines covered (59/59)
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
force-pushed
the
tte/fusion-write-forwarded-variables-once
branch
from
October 9, 2026 16:19
e8dd999 to
1294822
Compare
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.
Contributor
There was a problem hiding this comment.
🟢 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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When the gateway resolves an entity lookup,
FetchResultStorebuilds 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
mainmainmainmainmainmainmainmainmainThis 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. TheNonecases 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 inFetchResultStore, which are small next to the gain on exactly the fetch shape that batching produces.