Files
Workspace/Tools/AgentSupport/Benchmarks/TcpBenchmarks.cs
T
cneicy 08246ddb01
Validate ShrinkSDK Workspace / catalog (push) Successful in 5s
Validate ShrinkSDK Workspace / unity (push) Successful in 3m20s
feat: integrate performance upgrade and agent inspection tooling
2026-09-29 10:16:02 +08:00

75 lines
5.4 KiB
C#

using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Text.Json;
using Cysharp.Threading.Tasks;
using ShrinkNetwork;
public static class TcpBenchmarks
{
public static async Task Run(string output)
{
var rows = new List<object>();
foreach (var connections in new[] { 1, 32, 256 })
{
var probe = new TcpListener(IPAddress.Loopback, 0); probe.Start(); var port = ((IPEndPoint)probe.LocalEndpoint).Port; probe.Stop();
var transport = new ShrinkTcpServerTransport(IPAddress.Loopback, port);
var server = Service();
server.RegisterRequestHandler<NetworkTransportTests.Request, NetworkTransportTests.Response>((_, request) => UniTask.FromResult(new NetworkTransportTests.Response { Text = request.Text }));
server.BindTransport(transport);
var clients = new List<(ShrinkNetworkService service, ShrinkTcpClientTransport transport, ShrinkNetworkSession session)>();
long notifications = 0;
try
{
for (var i = 0; i < connections; i++)
{
var client = Service(); var link = new ShrinkTcpClientTransport("127.0.0.1", port);
var connected = new TaskCompletionSource<ShrinkNetworkSession>(TaskCreationOptions.RunContinuationsAsynchronously);
client.OnSessionConnected += s => connected.TrySetResult(s);
client.RegisterHandler<NetworkTransportTests.Request>((_, _) => { Interlocked.Increment(ref notifications); return UniTask.CompletedTask; });
client.BindTransport(link); clients.Add((client, link, await connected.Task.WaitAsync(TimeSpan.FromSeconds(10))));
}
foreach (var bytes in new[] { 64, 1024, 32768 })
{
var samples = new List<double>();
var message = new NetworkTransportTests.Request { Text = new string('t', bytes) };
var allocated = GC.GetTotalAllocatedBytes(true); var elapsed = Stopwatch.StartNew();
for (var i = 0; i < 256; i++)
{
var client = clients[i % clients.Count]; var start = Stopwatch.GetTimestamp();
var response = await client.service.CallAsync<NetworkTransportTests.Request, NetworkTransportTests.Response>(client.session, message).AsTask().WaitAsync(TimeSpan.FromSeconds(10));
if (response.Text.Length != bytes) throw new InvalidDataException("RPC content mismatch");
samples.Add(Stopwatch.GetElapsedTime(start).TotalMicroseconds);
}
samples.Sort();
rows.Add(new { scenario = "tcp/rpc", connections, bytes, operations = 256, throughputPerSecond = 256 / elapsed.Elapsed.TotalSeconds,
p50Microseconds = samples[128], p95Microseconds = samples[243], p99Microseconds = samples[253], processAllocatedBytes = GC.GetTotalAllocatedBytes(true) - allocated });
var payload = new ShrinkJsonNetworkSerializer().Serialize(message); var before = Interlocked.Read(ref notifications); elapsed.Restart();
foreach (var session in server.Sessions.Values) await server.SendSerializedAsync(session, typeof(NetworkTransportTests.Request), payload);
while (Interlocked.Read(ref notifications) - before < connections)
{ if (elapsed.Elapsed > TimeSpan.FromSeconds(10)) throw new TimeoutException("Broadcast drain"); await Task.Delay(1); }
rows.Add(new { scenario = "tcp/broadcast", connections, bytes, elapsedMilliseconds = elapsed.Elapsed.TotalMilliseconds, delivered = Interlocked.Read(ref notifications) - before });
}
using var queue = new ShrinkNetworkDispatchQueue(32, byteCapacity: 32768, perSessionCapacity: 2);
server.DispatchScheduler = queue;
var attempts = connections * 8;
for (var i = 0; i < attempts; i++)
{
var c = clients[i % clients.Count];
if (c.service.Sessions.Count != 0) try { await c.service.SendAsync(c.session, new NetworkTransportTests.Request { Text = new string('s', 1024) }); } catch (IOException) { }
}
await Task.Delay(100);
var beforePump = queue.CaptureDiagnostics(); await queue.PumpAsync(32, 8192, TimeSpan.FromMilliseconds(2));
rows.Add(new { scenario = "tcp/slow-consumer-burst", connections, attempts, beforePump, afterPump = queue.CaptureDiagnostics(), metrics = server.GetDiagnosticsSnapshot() });
}
finally { foreach (var c in clients) c.transport.Stop(); transport.Stop(); }
Console.WriteLine("TCP completed: " + connections);
}
await File.WriteAllTextAsync(output, JsonSerializer.Serialize(new { runtime = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription, host = "Windows loopback TCP; sequential round-trip samples, multiple real connections", rows }, new JsonSerializerOptions { WriteIndented = true }));
}
private static ShrinkNetworkService Service()
{
var service = new ShrinkNetworkService(); service.RegisterMessage<NetworkTransportTests.Request>(1); service.RegisterMessage<NetworkTransportTests.Response>(2); return service;
}
}