Skip to content

[Fusion] Recycle per-request arrays in the fetch result store - #10711

Merged
michaelstaib merged 5 commits into
ChilliCream:mainfrom
michaelstaib:perf/fetch-store-arrays
Oct 27, 2026
Merged

michaelstaib merged 5 commits into
ChilliCream:mainfrom
michaelstaib:perf/fetch-store-arrays

Conversation

@michaelstaib

Copy link
Copy Markdown
Member

The fetch result store allocated a new array of variable values for every subgraph lookup, grew its list of source documents one entry at a time, and created a new value completion helper for every request. These arrays are now kept on the pooled result store and reused by the next request, the source document table is rented from the array pool, and the helper is reused. Parsed source documents also keep less bookkeeping after parsing.

Metric Before Optimization After Optimization
Throughput 4,453 req/s 4,491 req/s (within noise)
Latency p50 10.04 ms 9.90 ms
CPU per request 0.817 ms 0.805 ms
Memory allocated per request 32.5 KB 30.3 KB (-6.8%)
GC collections per second 12.5 12.7
Memory usage (avg working set) 162.9 MB 164.4 MB

Measured on the federation benchmark twin machine with the benchmark's deep-recursion query (constant 50 VUs, gateway pinned to 4 logical cores), median of 4 interleaved 60 s runs against main. Throughput differences below about 2% are within run-to-run noise.

The fetch result store now hands out the exact-length VariableValues[]
arrays of its lookups from a small per-store free list instead of copying
every lookup's value sets into a new array. Leased arrays are cleared and
recycled when the store is cleaned and, for subscription events, when the
store is reset for the next event; value sets created before the first
event stay valid until the store is cleaned. Retention is bounded to 32
arrays and 256 entries per store. Entity reuse compacts the remaining value
sets into a leased array instead of an ImmutableArray builder and returns
the producer value sets right away.

CompositeResultDocument rents its source document table from the shared
array pool and returns it on Dispose instead of growing a List per request.
The store keeps one ValueCompletion and re-initializes it per request and
event, and SourceResultDocument keeps only the chunk table of its MetaDb
after parsing, which shrinks every parsed source document.
Trim the free list of variable value arrays on every recycle, not only when
leased arrays were moved back. Arrays that entity reuse returns mid-request
go straight to the free list, so a request or event whose leased arrays were
all returned skipped the trim and let the free list grow past the 32 array
and 256 entry retention bound. The first subscription event trims the arrays
returned during setup as well.
…ch-store-arrays

# Conflicts:
#	src/HotChocolate/Fusion/test/Fusion.Execution.Tests/Text/Json/CompositeResultDocumentTests.cs
@michaelstaib
michaelstaib merged commit 026d58c into ChilliCream:main Oct 27, 2026
151 checks passed
This was referenced Oct 29, 2026
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.

1 participant