feat: integrate performance upgrade and agent inspection tooling
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user