Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
220 commits
Select commit Hold shift + click to select a range
35aae83
chore: start fusion perf experiment 2
michaelstaib Feb 26, 2026
3c1fad6
Fusion: skip error trie lookups on clean completion paths
michaelstaib Feb 26, 2026
44bafe7
Revert "Fusion: skip error trie lookups on clean completion paths"
michaelstaib Feb 26, 2026
847e9d3
Fusion: avoid pending-request copy on group dispatch
michaelstaib Feb 26, 2026
c1c9da7
Revert "Fusion: avoid pending-request copy on group dispatch"
michaelstaib Feb 26, 2026
422492d
Fusion: reduce list completion branching overhead
michaelstaib Feb 26, 2026
d17587c
Fusion: simplify node response queue synchronization
michaelstaib Feb 26, 2026
11b4ae3
Revert "Fusion: simplify node response queue synchronization"
michaelstaib Feb 26, 2026
ef5b2d9
Fusion: defer operation result buffer sizing
michaelstaib Feb 26, 2026
5fc6063
Revert "Fusion: defer operation result buffer sizing"
michaelstaib Feb 26, 2026
21c839c
Fusion: skip object error trie lookup on fast path
michaelstaib Feb 26, 2026
8c84e4b
Revert "Fusion: skip object error trie lookup on fast path"
michaelstaib Feb 26, 2026
d8ad21b
Fusion: use indexed alias path loops in response stream
michaelstaib Feb 26, 2026
66c1f24
Revert "Fusion: use indexed alias path loops in response stream"
michaelstaib Feb 26, 2026
c0f8904
Fusion: streamline list completion leaf fast path
michaelstaib Feb 26, 2026
b4b5968
Revert "Fusion: streamline list completion leaf fast path"
michaelstaib Feb 26, 2026
27e56fd
Fusion: cache list object element type in completion
michaelstaib Feb 26, 2026
dc8cb42
Fusion: specialize value completion for no-error paths
michaelstaib Feb 26, 2026
eb6c4a0
Revert "Fusion: specialize value completion for no-error paths"
michaelstaib Feb 27, 2026
482a330
Fusion: reduce dedup hash lookups in variable set fast path
michaelstaib Feb 27, 2026
9ac1762
Revert "Fusion: reduce dedup hash lookups in variable set fast path"
michaelstaib Feb 27, 2026
795d919
Fusion: cache list object selection sets in completion
michaelstaib Feb 27, 2026
63c80b6
Merge remote-tracking branch 'origin/main' into mst/fusion-perf-exper…
michaelstaib Feb 27, 2026
27a14ff
Fusion: fast-path selection-based property completion
michaelstaib Feb 27, 2026
0b4a399
Fusion: precompute object cursor for selection completion
michaelstaib Feb 27, 2026
58b32fc
Fusion: specialize list completion for no-error path
michaelstaib Feb 27, 2026
e6b1945
Revert "Fusion: specialize list completion for no-error path"
michaelstaib Feb 27, 2026
22fbfd1
Fusion: tighten selection lookup hot path
michaelstaib Feb 27, 2026
99577e6
Fusion: fast-path tiny selection lookups
michaelstaib Feb 27, 2026
34911a1
Revert "Fusion: fast-path tiny selection lookups"
michaelstaib Feb 27, 2026
7ce8fae
Fusion: skip trie probes on no-error completion
michaelstaib Feb 27, 2026
78909ed
Fusion: cache concrete selection sets by selection id
michaelstaib Feb 27, 2026
73e773d
Revert "Fusion: cache concrete selection sets by selection id"
michaelstaib Feb 27, 2026
6f0679e
Fusion: precompute selection result cursor offsets
michaelstaib Feb 27, 2026
63dfe66
Revert "Fusion: precompute selection result cursor offsets"
michaelstaib Feb 27, 2026
4d32fea
Fusion: iterate start-result path with pooled segments
michaelstaib Feb 27, 2026
be5f63b
Fusion: reuse start-path buffer in fetch result store
michaelstaib Feb 27, 2026
b161f0e
Revert "Fusion: reuse start-path buffer in fetch result store"
michaelstaib Feb 27, 2026
06cf3a4
Fusion: fast-path list completion without error trie
michaelstaib Feb 27, 2026
82314b4
Merge remote-tracking branch 'origin/main' into mst/fusion-perf-exper…
michaelstaib Feb 27, 2026
ef3a0dd
Fusion: fast-path object list completion without trie
michaelstaib Feb 27, 2026
dd45bb1
Fusion: fast-path short path start result lookup
michaelstaib Feb 27, 2026
83be9c3
Revert "Fusion: fast-path short path start result lookup"
michaelstaib Feb 27, 2026
30b75e2
Fusion: fast-path small utf8 selection lookups
michaelstaib Feb 27, 2026
0852bcd
Fusion: extend utf8 selection fast-path to 4 fields
michaelstaib Feb 27, 2026
e6fa790
Fusion: cache selection value offsets for result lookup
michaelstaib Feb 27, 2026
25fbf2a
Revert "Fusion: cache selection value offsets for result lookup"
michaelstaib Feb 27, 2026
4f1699d
Fusion: linear-scan utf8 selection sets up to 8 fields
michaelstaib Feb 27, 2026
df1714e
Revert "Fusion: linear-scan utf8 selection sets up to 8 fields"
michaelstaib Feb 27, 2026
ad8abb1
Fusion: cache source value kind in value completion
michaelstaib Feb 27, 2026
78e9190
chore: retrigger benchmark run
michaelstaib Feb 27, 2026
d4b7bcc
Fusion: linear-scan medium utf8 selection sets
michaelstaib Feb 27, 2026
f657e4f
Merge remote-tracking branch 'origin/main' into mst/fusion-perf-exper…
michaelstaib Feb 27, 2026
7bdd32a
Fusion: use direct array cursor access in list completion
michaelstaib Feb 27, 2026
5aff290
Fusion: cache utf8 selection path segments
michaelstaib Feb 27, 2026
cbc1054
Fusion: use utf8 lookup in target collection
michaelstaib Feb 27, 2026
f7568df
Fusion: hoist segment-kind branch in target collection
michaelstaib Feb 27, 2026
49bda11
Fusion: reuse path segment buffer for start result lookup
michaelstaib Feb 27, 2026
3858df0
Fusion: use indexed loops in fetch result traversal
michaelstaib Feb 28, 2026
ebced76
Fusion: cache fast-path value kind checks
michaelstaib Feb 28, 2026
cd15bf2
Merge branch 'main' into mst/fusion-perf-experiment-2
michaelstaib Feb 28, 2026
ec9faea
Fusion: cache small int value nodes in result mapper
michaelstaib Feb 28, 2026
ee011ce
Fusion: cache selection set lookup in value completion
michaelstaib Feb 28, 2026
f315b66
Fusion: add ordered selection fast-path in value completion
michaelstaib Mar 1, 2026
5ecc377
Revert "Fusion: add ordered selection fast-path in value completion"
michaelstaib Mar 1, 2026
936ea9f
Fusion: add leaf scalar fast-path in value completion
michaelstaib Mar 1, 2026
e7ae7f4
Fusion: simplify selection-set cache storage
michaelstaib Mar 1, 2026
9edc6ed
Revert "Fusion: simplify selection-set cache storage"
michaelstaib Mar 1, 2026
4456b43
Fusion: fast-skip scalar values in source object enumerator
michaelstaib Mar 1, 2026
5977625
Revert "Fusion: fast-skip scalar values in source object enumerator"
michaelstaib Mar 1, 2026
39481b6
Fusion: use unchecked result element fast-paths in completion
michaelstaib Mar 1, 2026
2ee0555
Revert "Fusion: use unchecked result element fast-paths in completion"
michaelstaib Mar 1, 2026
ec06c33
Fusion: use fast property name span in value completion
michaelstaib Mar 1, 2026
0b00e19
Revert "Fusion: use fast property name span in value completion"
michaelstaib Mar 1, 2026
ab88808
Fusion: use fast end-index lookup in source enumerators
michaelstaib Mar 1, 2026
bebc08c
Revert "Fusion: use fast end-index lookup in source enumerators"
michaelstaib Mar 1, 2026
bf19421
Fusion: cache object type definition on selection
michaelstaib Mar 1, 2026
f1df5a9
Revert "Fusion: cache object type definition on selection"
michaelstaib Mar 1, 2026
fbbb3e5
Merge branch 'main' into mst/fusion-perf-experiment-2
michaelstaib Mar 1, 2026
d4ac3b3
Fusion: reduce cursor math in selection property lookup
michaelstaib Mar 1, 2026
4e95bc8
Revert "Fusion: reduce cursor math in selection property lookup"
michaelstaib Mar 1, 2026
64fdff8
Fusion: simplify list element type-kind checks
michaelstaib Mar 1, 2026
e898f54
Revert "Fusion: simplify list element type-kind checks"
michaelstaib Mar 1, 2026
282cf20
Fusion: fast-path next cursor in object enumeration
michaelstaib Mar 1, 2026
d8d976e
Revert "Fusion: fast-path next cursor in object enumeration"
michaelstaib Mar 1, 2026
eae445b
Fusion: reuse utf8 field names in variable set fast paths
michaelstaib Mar 1, 2026
f028847
Revert "Fusion: reuse utf8 field names in variable set fast paths"
michaelstaib Mar 1, 2026
132dc36
Fusion: fast-path ordered selection matching in object completion
michaelstaib Mar 1, 2026
ed6d6be
Revert "Fusion: fast-path ordered selection matching in object comple…
michaelstaib Mar 1, 2026
095ce17
Fusion: use token checks for null and object completion guards
michaelstaib Mar 1, 2026
02be4b8
Revert "Fusion: use token checks for null and object completion guards"
michaelstaib Mar 1, 2026
21600a2
Fusion: enumerate unrolled list elements linearly
michaelstaib Mar 1, 2026
ef3443a
Merge remote-tracking branch 'origin/main' into mst/fusion-perf-exper…
michaelstaib Mar 1, 2026
c03cc7b
Fusion: streamline dependent membership checks in execution state
michaelstaib Mar 1, 2026
23b978e
Revert "Fusion: streamline dependent membership checks in execution s…
michaelstaib Mar 1, 2026
7b471b2
Fusion: avoid duplicate array bounds traversal in start path resolution
michaelstaib Mar 1, 2026
920613c
Revert "Fusion: avoid duplicate array bounds traversal in start path …
michaelstaib Mar 1, 2026
707a905
Fusion: inline no-error leaf fast path in value completion
michaelstaib Mar 1, 2026
1c55bed
Revert "Fusion: inline no-error leaf fast path in value completion"
michaelstaib Mar 1, 2026
031c25f
Fusion: add field-only target collection fast path
michaelstaib Mar 1, 2026
9a892b8
Revert "Fusion: add field-only target collection fast path"
michaelstaib Mar 1, 2026
36ac813
Fusion: fast-path string-pair dedupe in two-requirement mapping
michaelstaib Mar 1, 2026
a472813
Revert "Fusion: fast-path string-pair dedupe in two-requirement mapping"
michaelstaib Mar 1, 2026
32ab0a2
Fusion: fast-path short start-path resolution
michaelstaib Mar 1, 2026
656afab
Revert "Fusion: fast-path short start-path resolution"
michaelstaib Mar 1, 2026
e225dd6
Fusion: inline scalar leaf mapping fast path
michaelstaib Mar 1, 2026
8c26126
Revert "Fusion: inline scalar leaf mapping fast path"
michaelstaib Mar 1, 2026
529acb6
Fusion: unroll utf8 selection lookup for 5-7 fields
michaelstaib Mar 1, 2026
697b37d
Revert "Fusion: unroll utf8 selection lookup for 5-7 fields"
michaelstaib Mar 1, 2026
ef432e5
stuff
michaelstaib Mar 1, 2026
63ed40e
Revert "stuff"
michaelstaib Mar 1, 2026
3f8f3da
Fusion: lazily initialize single-requirement dedupe maps
michaelstaib Mar 1, 2026
f198a20
Revert "Fusion: lazily initialize single-requirement dedupe maps"
michaelstaib Mar 1, 2026
0fc2a90
Fusion: cache segment utf8 names in target collection
michaelstaib Mar 1, 2026
4324759
Revert "Fusion: cache segment utf8 names in target collection"
michaelstaib Mar 1, 2026
e8dd4bc
Fusion: use utf8 property lookup in requirement fast paths
michaelstaib Mar 1, 2026
39de121
Revert "Fusion: use utf8 property lookup in requirement fast paths"
michaelstaib Mar 1, 2026
8f90413
Fusion: inline requirement mapping loop
michaelstaib Mar 1, 2026
e11c951
Revert "Fusion: inline requirement mapping loop"
michaelstaib Mar 1, 2026
822186d
Fusion: cache segment utf8 names in target traversal
michaelstaib Mar 1, 2026
b896e33
Revert "Fusion: cache segment utf8 names in target traversal"
michaelstaib Mar 1, 2026
887874e
Fusion: cache field utf8 name in target traversal
michaelstaib Mar 1, 2026
5695a07
Revert "Fusion: cache field utf8 name in target traversal"
michaelstaib Mar 1, 2026
5c73ccc
Fusion: lazily init single-requirement dedupe maps
michaelstaib Mar 1, 2026
158bdea
Revert "Fusion: lazily init single-requirement dedupe maps"
michaelstaib Mar 1, 2026
b19cb4a
Fusion: defer op node buffer sizing to second result
michaelstaib Mar 1, 2026
70cc334
Fusion: defer batch node buffer sizing to second result
michaelstaib Mar 1, 2026
2ae1c06
Revert "Fusion: defer batch node buffer sizing to second result"
michaelstaib Mar 1, 2026
c139fad
Fusion: add single-result partial-store fast path
michaelstaib Mar 1, 2026
bd3b76b
Revert "Fusion: add single-result partial-store fast path"
michaelstaib Mar 1, 2026
ea48179
Fusion: keep single-variable aliases in AdditionalPaths
michaelstaib Mar 1, 2026
f97263b
Revert "Fusion: keep single-variable aliases in AdditionalPaths"
michaelstaib Mar 1, 2026
31670a1
Fusion: fast-path single source result reads
michaelstaib Mar 1, 2026
932bf9a
Revert "Fusion: fast-path single source result reads"
michaelstaib Mar 2, 2026
ee62dce
Fusion: add single-result result-store fast path
michaelstaib Mar 2, 2026
8a30aae
Fusion: fast-path forwarded variable mapping
michaelstaib Mar 2, 2026
e3d9d58
Revert "Fusion: fast-path forwarded variable mapping"
michaelstaib Mar 2, 2026
9c9ca64
Fusion: probe source errors via HasErrors in node loops
michaelstaib Mar 2, 2026
47f4e55
Revert "Fusion: probe source errors via HasErrors in node loops"
michaelstaib Mar 2, 2026
fcbe5a2
Fusion: gate node telemetry tracking on CollectTelemetry
michaelstaib Mar 2, 2026
25e0189
Fusion: cache response stream callback locals
michaelstaib Mar 2, 2026
6bf0bd1
Revert "Fusion: cache response stream callback locals"
michaelstaib Mar 2, 2026
f6ae8c3
Fusion: precompute node input requirement flag
michaelstaib Mar 2, 2026
22a93dd
Revert "Fusion: precompute node input requirement flag"
michaelstaib Mar 2, 2026
f2158ee
Fusion: defer diagnostics events access in operation nodes
michaelstaib Mar 2, 2026
6b70a5c
Revert "Fusion: defer diagnostics events access in operation nodes"
michaelstaib Mar 2, 2026
7864814
Fusion: skip telemetry-only node result data when disabled
michaelstaib Mar 2, 2026
ac1aea4
Fusion: skip no-op diagnostic scopes for node execution
michaelstaib Mar 2, 2026
db5340a
Revert "Fusion: skip no-op diagnostic scopes for node execution"
michaelstaib Mar 2, 2026
fc3e3f6
Fusion: short-circuit non-batched dispatcher requests earlier
michaelstaib Mar 2, 2026
ef35455
Revert "Fusion: short-circuit non-batched dispatcher requests earlier"
michaelstaib Mar 2, 2026
535f811
Fusion: fast-path full dependent execution
michaelstaib Mar 2, 2026
9d0d55b
Revert "Fusion: fast-path full dependent execution"
michaelstaib Mar 2, 2026
345d230
Fusion: fast-path single dependent completion
michaelstaib Mar 2, 2026
0467419
Revert "Fusion: fast-path single dependent completion"
michaelstaib Mar 2, 2026
11912ae
Fusion: avoid interface enumeration in group removal
michaelstaib Mar 2, 2026
e39442f
Revert "Fusion: avoid interface enumeration in group removal"
michaelstaib Mar 2, 2026
ad078e8
Fusion: fast-path pending state in dispatcher submit
michaelstaib Mar 2, 2026
2038f5f
Revert "Fusion: fast-path pending state in dispatcher submit"
michaelstaib Mar 2, 2026
6e1928c
Fusion: defer batch result buffer sizing
michaelstaib Mar 2, 2026
ec55279
Revert "Fusion: defer batch result buffer sizing"
michaelstaib Mar 2, 2026
809281c
Fusion: reduce forwarded variable set allocations
michaelstaib Mar 2, 2026
2a04316
Revert "Fusion: reduce forwarded variable set allocations"
michaelstaib Mar 2, 2026
a9caaea
Fusion: clear dynamic schema slots selectively
michaelstaib Mar 2, 2026
7218c3e
Revert "Fusion: clear dynamic schema slots selectively"
michaelstaib Mar 2, 2026
1c7505b
Fusion: avoid per-node result allocations
michaelstaib Mar 2, 2026
23718c1
Revert "Fusion: avoid per-node result allocations"
michaelstaib Mar 2, 2026
338eda1
Fusion: skip dynamic dependent lookup for non-node nodes
michaelstaib Mar 2, 2026
ea12656
Revert "Fusion: skip dynamic dependent lookup for non-node nodes"
michaelstaib Mar 2, 2026
affc62c
Fusion: fast path single forwarded variable lookup
michaelstaib Mar 2, 2026
d7b4804
Revert "Fusion: fast path single forwarded variable lookup"
michaelstaib Mar 2, 2026
2762d00
Fusion: reduce dependency countdown branches
michaelstaib Mar 2, 2026
2142528
Revert "Fusion: reduce dependency countdown branches"
michaelstaib Mar 2, 2026
5060384
Fusion: remove redundant SelectionPath null checks
michaelstaib Mar 2, 2026
45403ff
Revert "Fusion: remove redundant SelectionPath null checks"
michaelstaib Mar 2, 2026
6e4b168
Merge branch 'main' into mst/fusion-perf-experiment-2
michaelstaib Mar 2, 2026
eaed8c9
Fusion: avoid Query parsing on single POST requests
michaelstaib Mar 2, 2026
0e670b0
Revert "Fusion: avoid Query parsing on single POST requests"
michaelstaib Mar 2, 2026
d7f02d5
Fusion: skip unnecessary request disposal registration
michaelstaib Mar 2, 2026
6697d9d
Revert "Fusion: skip unnecessary request disposal registration"
michaelstaib Mar 2, 2026
05fe2bb
perf: avoid async state machine in executor session fast path
michaelstaib Mar 2, 2026
0789b02
Revert "perf: avoid async state machine in executor session fast path"
michaelstaib Mar 2, 2026
840c591
perf: skip unused source schema transport callbacks
michaelstaib Mar 2, 2026
f9b7414
Revert "perf: skip unused source schema transport callbacks"
michaelstaib Mar 2, 2026
1fbdadc
perf: remove redundant charset from source schema accept headers
michaelstaib Mar 2, 2026
b996b41
perf: skip unused source schema transport delegate wiring
michaelstaib Mar 2, 2026
2bea732
Revert "perf: skip unused source schema transport delegate wiring"
michaelstaib Mar 2, 2026
1807fc6
perf: reduce initial transport response chunk rent
michaelstaib Mar 2, 2026
a33d2a1
Revert "perf: reduce initial transport response chunk rent"
michaelstaib Mar 2, 2026
f5b03a7
perf: avoid query parsing on single post path
michaelstaib Mar 2, 2026
6c3fc77
Revert "perf: avoid query parsing on single post path"
michaelstaib Mar 2, 2026
c4aaf54
perf: fast-path common fusion accept headers
michaelstaib Mar 2, 2026
5d41f84
Revert "perf: fast-path common fusion accept headers"
michaelstaib Mar 2, 2026
f71be65
perf: return superseded transport chunk arrays to pool
michaelstaib Mar 2, 2026
fc806a1
perf: remove redundant accept header clear in transport client
michaelstaib Mar 4, 2026
4601661
Revert "perf: remove redundant accept header clear in transport client"
michaelstaib Mar 4, 2026
e07a116
perf: fast-path common accept headers in transport client
michaelstaib Mar 4, 2026
933470c
Revert "perf: fast-path common accept headers in transport client"
michaelstaib Mar 4, 2026
e16d363
perf: avoid media type allocations in transport content headers
michaelstaib Mar 4, 2026
fb0e193
Revert "perf: avoid media type allocations in transport content headers"
michaelstaib Mar 4, 2026
1b91ce5
perf: avoid linq in pipeline header extensions
michaelstaib Mar 4, 2026
482f5b6
Revert "perf: avoid linq in pipeline header extensions"
michaelstaib Mar 4, 2026
d13a4ee
perf: fast-path utf8 charset handling in transport response
michaelstaib Mar 4, 2026
ed1bce4
Revert "perf: fast-path utf8 charset handling in transport response"
michaelstaib Mar 4, 2026
007a673
perf: avoid list growth in source schema batch requests
michaelstaib Mar 4, 2026
a41229f
perf: avoid builder allocation in source schema batch responses
michaelstaib Mar 4, 2026
ea7134a
Revert "perf: avoid builder allocation in source schema batch responses"
michaelstaib Mar 4, 2026
e3f0fe3
perf: avoid interface enumeration in group node cleanup
michaelstaib Mar 4, 2026
2ef663b
Revert "perf: avoid interface enumeration in group node cleanup"
michaelstaib Mar 4, 2026
9caff10
perf: avoid linked cts in json result stream reader
michaelstaib Mar 4, 2026
a10129b
Revert "perf: avoid linked cts in json result stream reader"
michaelstaib Mar 4, 2026
e2b749b
perf: use code page check for charset transcoding
michaelstaib Mar 4, 2026
78a9c8c
Revert "perf: use code page check for charset transcoding"
michaelstaib Mar 4, 2026
a8436d4
perf: fast-path single segment pipeline request parsing
michaelstaib Mar 4, 2026
8179c64
Revert "perf: fast-path single segment pipeline request parsing"
michaelstaib Mar 4, 2026
80bb2bd
perf: avoid copy when dispatching grouped source requests
michaelstaib Mar 4, 2026
68de634
Revert "perf: avoid copy when dispatching grouped source requests"
michaelstaib Mar 4, 2026
2edd6f1
perf: remove dispatcher async trampoline
michaelstaib Mar 4, 2026
9ea2ccc
Revert "perf: remove dispatcher async trampoline"
michaelstaib Mar 4, 2026
129ab7f
perf: avoid no-op request dispose registration
michaelstaib Mar 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,13 @@ await session.RequestParser.ParseRequestAsync(

foreach (var request in requests)
{
context.Response.RegisterForDispose(request);
if (request.Variables is not null
|| request.Extensions is not null
|| request.VariablesMemoryOwner is not null
|| request.ExtensionsMemoryOwner is not null)
{
context.Response.RegisterForDispose(request);
}
}

return requests;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,15 @@ private async ValueTask<OperationResult> ReadAsResultInternalAsync(string? charS
var chunkIndex = 0;
var chunks = ArrayPool<byte[]>.Shared.Rent(64);

static byte[][] GrowChunkArray(byte[][] chunkArray)
{
var newChunks = ArrayPool<byte[]>.Shared.Rent(chunkArray.Length * 2);
Array.Copy(chunkArray, 0, newChunks, 0, chunkArray.Length);
chunkArray.AsSpan().Clear();
ArrayPool<byte[]>.Shared.Return(chunkArray);
return newChunks;
}

try
{
while (true)
Expand Down Expand Up @@ -219,10 +228,7 @@ private async ValueTask<OperationResult> ReadAsResultInternalAsync(string? charS
{
if (chunkIndex >= chunks.Length)
{
var newChunks = ArrayPool<byte[]>.Shared.Rent(chunks.Length * 2);
Array.Copy(chunks, 0, newChunks, 0, chunks.Length);
chunks.AsSpan().Clear();
chunks = newChunks;
chunks = GrowChunkArray(chunks);
}

chunks[chunkIndex++] = currentChunk;
Expand Down Expand Up @@ -257,10 +263,7 @@ private async ValueTask<OperationResult> ReadAsResultInternalAsync(string? charS
{
if (chunkIndex >= chunks.Length)
{
var newChunks = ArrayPool<byte[]>.Shared.Rent(chunks.Length * 2);
Array.Copy(chunks, 0, newChunks, 0, chunks.Length);
chunks.AsSpan().Clear();
chunks = newChunks;
chunks = GrowChunkArray(chunks);
}

chunks[chunkIndex++] = currentChunk;
Expand All @@ -277,10 +280,7 @@ private async ValueTask<OperationResult> ReadAsResultInternalAsync(string? charS
// add the final partial chunk to the list
if (chunkIndex >= chunks.Length)
{
var newChunks = ArrayPool<byte[]>.Shared.Rent(chunks.Length * 2);
Array.Copy(chunks, 0, newChunks, 0, chunks.Length);
chunks.AsSpan().Clear();
chunks = newChunks;
chunks = GrowChunkArray(chunks);
}

chunks[chunkIndex++] = currentChunk;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ private GraphQLHttpRequest CreateHttpRequest(
private GraphQLHttpRequest CreateHttpBatchRequest(
IReadOnlyList<SourceSchemaClientRequest> originalRequests)
{
var batchRequests = new List<IOperationRequest>(originalRequests.Count);
var batchRequests = new IOperationRequest[originalRequests.Count];
var enableFileUploads = false;

for (var i = 0; i < originalRequests.Count; i++)
Expand All @@ -200,15 +200,13 @@ private GraphQLHttpRequest CreateHttpBatchRequest(
enableFileUploads |= sourceRequest.RequiresFileUpload;

var body = CreateRequestBody(sourceRequest);
if (body is IOperationRequest operationRequest)
{
batchRequests.Add(operationRequest);
}
else
if (body is not IOperationRequest operationRequest)
{
throw new InvalidOperationException(
$"The request body type '{body.GetType().Name}' cannot be included in an operation batch.");
}

batchRequests[i] = operationRequest;
}

return new GraphQLHttpRequest(new OperationBatchRequest(batchRequests))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,29 +218,29 @@ private static class AcceptContentTypes
{
public static ImmutableArray<MediaTypeWithQualityHeaderValue> Default { get; } =
[
new("application/graphql-response+json") { CharSet = "utf-8" },
new("application/json") { CharSet = "utf-8" },
new("application/jsonl") { CharSet = "utf-8" },
new("text/event-stream") { CharSet = "utf-8" }
new("application/graphql-response+json"),
new("application/json"),
new("application/jsonl"),
new("text/event-stream")
];

public static ImmutableArray<MediaTypeWithQualityHeaderValue> VariableBatching { get; } =
[
new("application/jsonl") { CharSet = "utf-8" },
new("text/event-stream") { CharSet = "utf-8" },
new("application/graphql-response+json") { CharSet = "utf-8" },
new("application/json") { CharSet = "utf-8" }
new("application/jsonl"),
new("text/event-stream"),
new("application/graphql-response+json"),
new("application/json")
];

public static ImmutableArray<MediaTypeWithQualityHeaderValue> ApolloRequestBatching { get; } =
[
new("application/json") { CharSet = "utf-8" }
new("application/json")
];

public static ImmutableArray<MediaTypeWithQualityHeaderValue> Subscription { get; } =
[
new("application/jsonl") { CharSet = "utf-8" },
new("text/event-stream") { CharSet = "utf-8" }
new("application/jsonl"),
new("text/event-stream")
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ public async Task ExecuteAsync(
OperationPlanContext context,
CancellationToken cancellationToken = default)
{
var start = Stopwatch.GetTimestamp();
var collectTelemetry = context.CollectTelemetry;
var start = collectTelemetry ? Stopwatch.GetTimestamp() : 0L;
var scope = CreateScope(context);
var activity = Activity.Current;
var activity = collectTelemetry ? Activity.Current : null;
ExecutionStatus status;
Exception? error = null;

Expand All @@ -78,15 +79,20 @@ public async Task ExecuteAsync(
scope?.Dispose();
}

var duration = collectTelemetry ? Stopwatch.GetElapsedTime(start) : default;
var dependentsToExecute = context.GetDependentsToExecute(this);
var variableValueSets = collectTelemetry ? context.GetVariableValueSets(this) : [];
var transportDetails = collectTelemetry ? context.GetTransportDetails(this) : default;

var result = new ExecutionNodeResult(
Id,
activity,
status,
Stopwatch.GetElapsedTime(start),
duration,
error,
context.GetDependentsToExecute(this),
context.GetVariableValueSets(this),
context.GetTransportDetails(this));
dependentsToExecute,
variableValueSets,
transportDetails);

context.CompleteNode(result);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Buffers;
using System.Collections.Immutable;
using System.Runtime.InteropServices;
using HotChocolate.Fusion.Execution.Clients;

namespace HotChocolate.Fusion.Execution.Nodes;
Expand Down Expand Up @@ -112,7 +111,12 @@ protected override async ValueTask<ExecutionStatus> OnExecuteAsync(

var schemaName = _schemaName ?? context.GetDynamicSchemaName(this);

context.TrackVariableValueSets(this, variables);
var collectTelemetry = context.CollectTelemetry;

if (collectTelemetry)
{
context.TrackVariableValueSets(this, variables);
}

var request = new SourceSchemaClientRequest
{
Expand All @@ -137,7 +141,10 @@ protected override async ValueTask<ExecutionStatus> OnExecuteAsync(
var response = await context.SourceSchemaScheduler
.ExecuteAsync(request, cancellationToken)
.ConfigureAwait(false);
context.TrackSourceSchemaClientResponse(this, response);
if (collectTelemetry)
{
context.TrackSourceSchemaClientResponse(this, response);
}

// we read the responses from the response stream.
var totalPathCount = variables.Length;
Expand Down Expand Up @@ -225,10 +232,9 @@ protected override async ValueTask<ExecutionStatus> OnExecuteAsync(
}
else if (singleResult is not null)
{
var firstResult = singleResult;
context.AddPartialResults(
context.AddPartialResult(
_source,
MemoryMarshal.CreateReadOnlySpan(ref firstResult, 1),
singleResult,
_responseNames,
hasSomeErrors);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,12 @@ protected override async ValueTask<ExecutionStatus> OnExecuteAsync(

var schemaName = _schemaName ?? context.GetDynamicSchemaName(this);

context.TrackVariableValueSets(this, variables);
var collectTelemetry = context.CollectTelemetry;

if (collectTelemetry)
{
context.TrackVariableValueSets(this, variables);
}

var request = new SourceSchemaClientRequest
{
Expand All @@ -143,18 +148,11 @@ protected override async ValueTask<ExecutionStatus> OnExecuteAsync(
var response = await context.SourceSchemaScheduler
.ExecuteAsync(request, cancellationToken)
.ConfigureAwait(false);
context.TrackSourceSchemaClientResponse(this, response);

// we read the responses from the response stream.
var totalPathCount = variables.Length;

for (var i = 0; i < variables.Length; i++)
if (collectTelemetry)
{
totalPathCount += variables[i].AdditionalPaths.Length;
context.TrackSourceSchemaClientResponse(this, response);
}

var initialBufferLength = Math.Max(totalPathCount, 2);

await foreach (var result in response.ReadAsResultStreamAsync(cancellationToken))
{
// If there is only one response, we skip the buffer rental.
Expand All @@ -168,7 +166,14 @@ protected override async ValueTask<ExecutionStatus> OnExecuteAsync(
// If we have more than one response, we rent a buffer and move the first result into it.
if (buffer is null)
{
bufferLength = initialBufferLength;
var totalPathCount = variables.Length;

for (var i = 0; i < variables.Length; i++)
{
totalPathCount += variables[i].AdditionalPaths.Length;
}

bufferLength = Math.Max(totalPathCount, 2);
buffer = ArrayPool<SourceSchemaResult>.Shared.Rent(bufferLength);
buffer[0] = singleResult!;
}
Expand Down Expand Up @@ -229,10 +234,9 @@ protected override async ValueTask<ExecutionStatus> OnExecuteAsync(
}
else if (singleResult is not null)
{
var firstResult = singleResult;
context.AddPartialResults(
context.AddPartialResult(
_source,
MemoryMarshal.CreateReadOnlySpan(ref firstResult, 1),
singleResult,
_responseNames,
hasSomeErrors);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public sealed class Selection : ISelection
private readonly FieldSelectionNode[] _syntaxNodes;
private readonly ulong[] _includeFlags;
private readonly byte[] _utf8ResponseName;
private SelectionSetCacheEntry? _selectionSetCache;
private Flags _flags;

public Selection(
Expand Down Expand Up @@ -44,6 +45,17 @@ public Selection(
_flags |= Flags.Leaf;
}

IType fieldType = field.Type;
while (fieldType.Kind is TypeKind.NonNull)
{
fieldType = fieldType.InnerType();
}

if (fieldType.Kind is TypeKind.Scalar or TypeKind.Enum)
{
_flags |= Flags.LeafValue;
}

_utf8ResponseName = Utf8StringCache.GetUtf8String(responseName);
}

Expand All @@ -64,6 +76,8 @@ public Selection(
/// <inheritdoc />
public bool IsLeaf => (_flags & Flags.Leaf) == Flags.Leaf;

internal bool IsLeafValue => (_flags & Flags.LeafValue) == Flags.LeafValue;

/// <inheritdoc />
public IOutputFieldDefinition Field { get; }

Expand All @@ -85,6 +99,22 @@ public Selection(

internal ResolveFieldValue? Resolver => Field.Features.Get<ResolveFieldValue>();

internal SelectionSet GetSelectionSet(IObjectTypeDefinition typeContext)
{
ArgumentNullException.ThrowIfNull(typeContext);

var cache = _selectionSetCache;

if (cache is not null && ReferenceEquals(cache.TypeContext, typeContext))
{
return cache.SelectionSet;
}

var selectionSet = DeclaringSelectionSet.DeclaringOperation.GetSelectionSet(this, typeContext);
_selectionSetCache = new SelectionSetCacheEntry(typeContext, selectionSet);
return selectionSet;
}

IEnumerable<FieldNode> ISelection.GetSyntaxNodes()
{
for (var i = 0; i < SyntaxNodes.Length; i++)
Expand Down Expand Up @@ -169,6 +199,16 @@ private enum Flags
None = 0,
Internal = 1,
Leaf = 2,
Sealed = 4
Sealed = 4,
LeafValue = 8
}

private sealed class SelectionSetCacheEntry(
IObjectTypeDefinition typeContext,
SelectionSet selectionSet)
{
public IObjectTypeDefinition TypeContext { get; } = typeContext;

public SelectionSet SelectionSet { get; } = selectionSet;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Immutable;
using System.Text;
using HotChocolate.Fusion.Text;

namespace HotChocolate.Fusion.Execution.Nodes;

Expand Down Expand Up @@ -355,7 +356,13 @@ public override string ToString()
/// </summary>
/// <param name="Name">The name of the field or type for this segment.</param>
/// <param name="Kind">The kind of segment (field or inline fragment).</param>
public sealed record Segment(string Name, SelectionPathSegmentKind Kind);
public sealed record Segment(string Name, SelectionPathSegmentKind Kind)
{
private byte[]? _utf8Name;

public ReadOnlySpan<byte> Utf8Name
=> _utf8Name ??= Utf8StringCache.GetUtf8String(Name);
}

/// <summary>
/// Creates a new builder for creating <see cref="SelectionPath"/> instances.
Expand Down
Loading
Loading