perf(net): own one pooled async receive

Replace timeout-polled in-world UDP receives with one cancellable caller-buffered socket operation. Transfer only right-sized pooled datagrams through the FIFO, return every ownership edge deterministically, and send caller spans without a transport copy while preserving handshake pacing and ACK order.
This commit is contained in:
Erik 2026-07-25 05:50:18 +02:00
parent a2a1e5916d
commit 7211bb1bf7
10 changed files with 547 additions and 87 deletions

View file

@ -96,4 +96,50 @@ public class NetClientTests
Assert.Null(result);
Assert.Null(from);
}
[Fact]
public async Task ReceiveAsync_LoopbackWritesIntoCallerOwnedMemory()
{
using var serverSide =
new NetClient(new IPEndPoint(IPAddress.Loopback, 0));
using var clientSide =
new NetClient(new IPEndPoint(
IPAddress.Loopback,
serverSide.LocalEndPoint.Port));
byte[] outbound = Enumerable.Range(0, 1_500)
.Select(static value => (byte)value)
.ToArray();
byte[] destination = new byte[2_048];
using var timeout =
new CancellationTokenSource(TimeSpan.FromSeconds(2));
clientSide.Send(outbound);
NetReceiveResult result = await serverSide.ReceiveAsync(
destination,
timeout.Token);
Assert.Equal(outbound.Length, result.Length);
Assert.Equal(
outbound,
destination.AsSpan(0, result.Length).ToArray());
Assert.Equal(
clientSide.LocalEndPoint.Port,
result.RemoteEndPoint.Port);
}
[Fact]
public async Task ReceiveAsync_IdleCancellationStopsOutstandingReceive()
{
using var client =
new NetClient(new IPEndPoint(IPAddress.Loopback, 1));
byte[] destination = new byte[32];
using var cancellation = new CancellationTokenSource();
ValueTask<NetReceiveResult> receive =
client.ReceiveAsync(destination, cancellation.Token);
cancellation.Cancel();
await Assert.ThrowsAnyAsync<OperationCanceledException>(
async () => await receive);
}
}