Skip to content

Commit c6875d6

Browse files
authored
Merge branch 'main' into mst/docs-160326-1
2 parents a6c99b7 + 1ce7177 commit c6875d6

35 files changed

Lines changed: 2051 additions & 278 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"id": "abc",
3+
"type": "data",
4+
"payload": {
5+
"data": {
6+
"onReview": {
7+
"stars": 5
8+
}
9+
}
10+
}
11+
}

src/HotChocolate/Fusion/benchmarks/k6/deep-recursion.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { check } from "k6";
33
import { Rate } from "k6/metrics";
44
import { textSummary } from "https://jslib.k6.io/k6-summary/0.0.1/index.js";
55

6-
const GRAPHQL_URL = 'http://localhost:5220/graphql';
6+
const GRAPHQL_URL = 'http://localhost:5000/graphql';
77
const endpoint = __ENV.GATEWAY_ENDPOINT || GRAPHQL_URL;
88
const mode = __ENV.MODE || "constant";
99
const isConstant = mode === "constant";
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
using System.Diagnostics.Tracing;
2+
3+
namespace eShop.Gateway;
4+
5+
/// <summary>
6+
/// Listens to PathSegmentPool ETW events and logs aggregated usage metrics.
7+
/// </summary>
8+
internal sealed class PathSegmentPoolDiagnostics : EventListener, IHostedService
9+
{
10+
private readonly Timer _timer;
11+
12+
private int _poolId;
13+
private int _segmentSize;
14+
private int _maxArrays;
15+
private long _maxBytes;
16+
17+
private long _rented;
18+
private long _returned;
19+
private long _exhausted;
20+
private long _dropped;
21+
private long _allocated;
22+
private long _trimmedEvents;
23+
private int _lastTrimRemaining;
24+
private int _lastTrimInUse;
25+
private int _peakInUse;
26+
27+
public PathSegmentPoolDiagnostics()
28+
{
29+
_timer = new Timer(LogSnapshot, null, Timeout.Infinite, Timeout.Infinite);
30+
}
31+
32+
protected override void OnEventSourceCreated(EventSource eventSource)
33+
{
34+
if (eventSource.Name == "HotChocolate-Fusion-PathSegmentPool")
35+
{
36+
EnableEvents(eventSource, EventLevel.Verbose);
37+
}
38+
}
39+
40+
protected override void OnEventWritten(EventWrittenEventArgs e)
41+
{
42+
// Event IDs from PathSegmentPoolEventSource:
43+
// 1 = PoolCreated (PoolId, SegmentSize, Arrays, TotalBytes)
44+
// 2 = SegmentRented (ArrayId, Length, PoolId, InUse)
45+
// 3 = SegmentReturned (ArrayId, Length, PoolId, InUse)
46+
// 4 = PoolExhausted (PoolId, MaxArrays)
47+
// 5 = SegmentDropped (ArrayId, Length, PoolId)
48+
// 6 = SegmentAllocated(ArrayId, Length, PoolId)
49+
// 7 = PoolTrimmed (PoolId, Trimmed, Remaining, InUse)
50+
switch (e.EventId)
51+
{
52+
case 1:
53+
if (e.Payload is { Count: >= 4 })
54+
{
55+
if (e.Payload[0] is int poolId)
56+
{
57+
_poolId = poolId;
58+
}
59+
if (e.Payload[1] is int segmentSize)
60+
{
61+
_segmentSize = segmentSize;
62+
}
63+
if (e.Payload[2] is int maxArrays)
64+
{
65+
_maxArrays = maxArrays;
66+
}
67+
if (e.Payload[3] is long maxBytes)
68+
{
69+
_maxBytes = maxBytes;
70+
}
71+
}
72+
break;
73+
74+
case 2:
75+
Interlocked.Increment(ref _rented);
76+
if (e.Payload is { Count: >= 4 } && e.Payload[3] is int inUseRent)
77+
{
78+
UpdatePeakInUse(inUseRent);
79+
}
80+
break;
81+
82+
case 3:
83+
Interlocked.Increment(ref _returned);
84+
break;
85+
86+
case 4:
87+
Interlocked.Increment(ref _exhausted);
88+
break;
89+
90+
case 5:
91+
Interlocked.Increment(ref _dropped);
92+
break;
93+
94+
case 6:
95+
Interlocked.Increment(ref _allocated);
96+
break;
97+
98+
case 7:
99+
Interlocked.Increment(ref _trimmedEvents);
100+
if (e.Payload is { Count: >= 4 })
101+
{
102+
if (e.Payload[2] is int remaining)
103+
{
104+
_lastTrimRemaining = remaining;
105+
}
106+
if (e.Payload[3] is int inUseTrim)
107+
{
108+
_lastTrimInUse = inUseTrim;
109+
}
110+
}
111+
break;
112+
}
113+
}
114+
115+
private void UpdatePeakInUse(int inUse)
116+
{
117+
int current;
118+
do
119+
{
120+
current = _peakInUse;
121+
if (inUse <= current)
122+
{
123+
return;
124+
}
125+
}
126+
while (Interlocked.CompareExchange(ref _peakInUse, inUse, current) != current);
127+
}
128+
129+
private void LogSnapshot(object? state)
130+
{
131+
var rented = Interlocked.Read(ref _rented);
132+
var returned = Interlocked.Read(ref _returned);
133+
var exhausted = Interlocked.Read(ref _exhausted);
134+
var dropped = Interlocked.Read(ref _dropped);
135+
var allocated = Interlocked.Read(ref _allocated);
136+
var trimmedEvents = Interlocked.Read(ref _trimmedEvents);
137+
var outstanding = rented - returned;
138+
139+
Console.WriteLine(
140+
"[PathSegmentPool] PoolId={0}, SegmentSize={1}, MaxArrays={2}, MaxBytes={3}, "
141+
+ "Rented={4}, Returned={5}, Outstanding={6}, PeakInUse={7}, "
142+
+ "Exhausted={8}, Allocated={9}, Dropped={10}, "
143+
+ "TrimmedEvents={11}, LastTrimRemaining={12}, LastTrimInUse={13}",
144+
_poolId,
145+
_segmentSize,
146+
_maxArrays,
147+
_maxBytes,
148+
rented,
149+
returned,
150+
outstanding,
151+
_peakInUse,
152+
exhausted,
153+
allocated,
154+
dropped,
155+
trimmedEvents,
156+
_lastTrimRemaining,
157+
_lastTrimInUse);
158+
}
159+
160+
public Task StartAsync(CancellationToken cancellationToken)
161+
{
162+
Console.WriteLine("[PathSegmentPool] Diagnostics started");
163+
_timer.Change(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));
164+
return Task.CompletedTask;
165+
}
166+
167+
public Task StopAsync(CancellationToken cancellationToken)
168+
{
169+
_timer.Change(Timeout.Infinite, Timeout.Infinite);
170+
LogSnapshot(null);
171+
Console.WriteLine("[PathSegmentPool] Diagnostics stopped - final snapshot logged above");
172+
return Task.CompletedTask;
173+
}
174+
175+
public override void Dispose()
176+
{
177+
_timer.Dispose();
178+
base.Dispose();
179+
}
180+
}

src/HotChocolate/Fusion/benchmarks/k6/eShop.Gateway/Program.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ThreadPool.SetMinThreads(1024, 1024);
1+
ThreadPool.SetMinThreads(512, 512);
22

33
var builder = WebApplication.CreateBuilder(args);
44

@@ -11,8 +11,7 @@
1111

1212
builder
1313
.AddGraphQLGateway()
14-
.ModifyPlannerOptions(o => o.EnableRequestGrouping = true)
15-
.AddFileSystemConfiguration("./gateway.far");
14+
.AddFileSystemConfiguration("gateway.far");
1615

1716
var app = builder.Build();
1817

src/HotChocolate/Fusion/benchmarks/k6/eShop.Gateway/Properties/launchSettings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"commandName": "Project",
55
"dotnetRunMessages": true,
66
"launchBrowser": true,
7-
"launchUrl": "http://localhost:5220/graphql",
8-
"applicationUrl": "http://localhost:5220",
7+
"launchUrl": "http://localhost:5000/graphql",
8+
"applicationUrl": "http://localhost:5000",
99
"environmentVariables": {
1010
"ASPNETCORE_ENVIRONMENT": "Production"
1111
}

src/HotChocolate/Fusion/src/Fusion.Execution/DependencyInjection/HotChocolateFusionServiceCollectionExtensions.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using HotChocolate.Fusion.Configuration;
44
using HotChocolate.Fusion.Execution;
55
using HotChocolate.Fusion.Execution.Clients;
6+
using HotChocolate.Fusion.Execution.Results;
67
using HotChocolate.Language;
78
using Microsoft.Extensions.DependencyInjection.Extensions;
89
using Microsoft.Extensions.ObjectPool;
@@ -89,10 +90,18 @@ private static DefaultFusionGatewayBuilder CreateBuilder(
8990

9091
var builder = new DefaultFusionGatewayBuilder(services, name);
9192
builder.AddDocumentCache();
93+
builder.AddFetchResultStorePool();
9294
builder.UseDefaultPipeline();
9395
return builder;
9496
}
9597

98+
private static void AddFetchResultStorePool(this IFusionGatewayBuilder builder)
99+
=> builder.ConfigureSchemaServices(
100+
static (_, s) => s.TryAddSingleton(
101+
new FetchResultStorePool(
102+
levels: [4, 16, 64],
103+
trimInterval: TimeSpan.FromMinutes(5))));
104+
96105
private static IFusionGatewayBuilder AddDocumentCache(this IFusionGatewayBuilder builder)
97106
{
98107
builder.Services.TryAddKeyedSingleton<IDocumentCache>(

0 commit comments

Comments
 (0)