Repository navigation
[Fusion] Match duplicate lookup variables on raw leaf values - #10614
Open
tobias-tengler wants to merge 13 commits into
Open
tobias-tengler wants to merge 13 commits into
tobias-tengler wants to merge 13 commits into
Conversation
When one lookup result is merged into a primary target and several additional targets, the primary target is completed from the source data and, when every completed value is a non-null, non-enum leaf of an object with the same selection set, the completed rows are copied into each additional target instead of completing the same source data again. Targets that do not qualify, merges with errors and pocketed errors keep the existing completion.
Additional targets of a lookup variable set are kept as cursors into the result document instead of building a path per target. The merge uses the cursors directly while no value that references an object or a list was replaced since the targets were collected, and resolves the target from the root by its path otherwise. The paths of a CompactPathSegment are created on first access, so error attribution, telemetry and custom clients keep working.
The simple-requirement fast paths and Apollo representations with a leaf-only shape write the kind and raw bytes of the requirement values as a key and look it up before writing the variable JSON. A target whose key matches an earlier target joins that variable set without writing or hashing its JSON. Values that are not non-null leaves keep the existing JSON comparison.
Contributor
Patch coverage94.6% of changed lines covered (529/559)
Uncovered changed lines (JSON){
"sha": "e1e863bc4357294765a88bb754767f9801714d7a",
"files": [
{ "path": "src/HotChocolate/Fusion/src/Fusion.Connectors.InMemory/InMemorySourceSchemaClient.cs", "ranges": [[525, 525]] },
{ "path": "src/HotChocolate/Fusion/src/Fusion.Execution/Execution/Results/FetchResultStore.RepresentationValue.cs", "ranges": [[385, 385], [448, 450]] },
{ "path": "src/HotChocolate/Fusion/src/Fusion.Execution/Execution/Results/FetchResultStore.cs", "ranges": [[3417, 3418], [3441, 3443], [3453, 3453], [3455, 3456], [3472, 3473], [3489, 3493], [3561, 3562]] },
{ "path": "src/HotChocolate/Fusion/src/Fusion.Execution/Text/Json/ArenaBufferWriter.cs", "ranges": [[232, 233], [282, 283], [301, 302]] },
{ "path": "src/HotChocolate/Fusion/src/Fusion.Execution/JsonSegment.cs", "ranges": [[57, 57], [79, 79]] }
]
}Project coverage: 59.2% (313907/530240 lines) |
tobias-tengler
changed the base branch from
main
to
tte/fusion-duplicate-lookup-target-cursors
October 19, 2026 06:44
Base automatically changed from
tte/fusion-duplicate-lookup-target-cursors
to
main
October 21, 2026 05:51
- The leaf key table is initialized only by the requirement fast paths and the leaf-shape representation path that use it. - Clean trims both variable dedup tables when a lookup with many targets made them grow. - The variable set array is rented before the leaf key check, and a missing shape property marks the representation key invalid like other misses. - Tests cover strings and numbers with the same text, nullable null values, the two- and three-requirement paths, and leaf-shape representations. - Documentation states contracts.
michaelstaib
marked this pull request as ready for review
October 21, 2026 10:48
The variable writer of the result store now writes into the memory arena of the request, so a pooled store no longer holds a 128 KB chunk between requests. Each subscription event writes its variables with a new writer on the event arena, so variables no longer accumulate for the lifetime of the subscription. Cleaning the store releases the arena memory of the variable and leaf key writers.
A writer that stays within its first segment no longer rents a segment table, and the table starts with 16 entries.
Variables written to the request arena can split a JSON token across segments. The file upload paths of the HTTP transport and the in-memory client now read such tokens from the value sequence. Trace variable sets now own a copy of their values, so a trace stays readable after the result store returns to the pool.
JsonSegment now wraps the sequence of its bytes instead of a writer and a position. The arena and chunked writers hand out sequences over their memory, equality and hashing compare bytes, and the entity reuse lookup compares value sets by content. Traced variable values are copied into the arena of the plan context, so the trace stays valid when the variable writer writes its memory again. The result store keeps a single variable writer again, since segments no longer read through it.
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.
To deduplicate lookup variables, the gateway writes the variable JSON of every lookup target and compares it with the variable sets created so far. For the federation benchmark query this means 324 lookup targets but only 7 distinct variable sets, so most targets write and hash their variable JSON only to join a variable set that already exists.
This PR writes a key of the raw requirement values (value kind and raw leaf bytes) in the simple-requirement fast paths and for Apollo representations with a leaf-only shape, and looks it up before writing the variable JSON. A target whose key matches an earlier target joins that variable set without writing or hashing JSON. Requirement values that are not non-null leaves keep the existing JSON comparison.
CreateVariableValueSetsfor 156 product targets on three nested paths with 5 distinct keys. Variable creation with one requirement is 17% faster, well beyond the error interval, at the same allocations. The three-requirement case moves the same way, but its base run is too noisy to put a number on it.