perf(gateway): pool+coalesce worker pipe frame I/O (GWC-08, IPC-13, IPC-14)
Gateway server-side named-pipe frame path, wire format byte-identical: - Writer (GWC-08/IPC-13): serialize once into a single ArrayPool-rented buffer holding the 4-byte LE length prefix + payload, then one WriteAsync. Removes the second serialization pass (ToByteArray re-ran CalculateSize), the separate prefix array + second stream write, and per-frame heap allocation. - Reader (IPC-14): rent the payload buffer from ArrayPool instead of new byte[] per frame; read/parse bounded to the real length, return in finally. Matches the worker side which already pools. - Correctness: length tracked separately from (larger) pool capacity; every rented buffer returned exactly once in finally incl. the malformed-protobuf path; ParseFrom copies into the message so the envelope never aliases the returned buffer. Cross-checked LE-prefix framing agrees across gateway+worker writer/reader. Server build clean (0 warnings); WorkerFrameProtocol tests 10/10 incl. a new large-payload-near-cap round-trip (forces pool buffer > frame). The 2 failing WorkerClient/FakeWorkerHarness tests are the known macOS UDS 104-char path limit, not a regression. Claude-Session: https://claude.ai/code/session_01DMXXvNuPekkkrTEyPNxEkW
This commit is contained in:
@@ -29,6 +29,32 @@ public sealed class WorkerFrameProtocolTests
|
||||
Assert.Equal(original, parsed);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a large payload near the message cap round-trips through the pooled write/read path.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task WriteAndReadAsync_WithLargePayloadNearMax_RoundTripsFrame()
|
||||
{
|
||||
// A payload comfortably larger than an ArrayPool bucket boundary so the rented buffer is
|
||||
// larger than the exact frame length, exercising the length-bounded read and parse.
|
||||
const int maxMessageBytes = 1024 * 1024;
|
||||
WorkerFrameProtocolOptions options =
|
||||
new(SessionId, GatewayContractInfo.WorkerProtocolVersion, maxMessageBytes);
|
||||
await using MemoryStream stream = new();
|
||||
|
||||
WorkerEnvelope original = CreateEnvelope();
|
||||
original.WorkerHello.WorkerVersion = new string('x', maxMessageBytes - 4096);
|
||||
Assert.InRange(original.CalculateSize(), 1, maxMessageBytes);
|
||||
|
||||
WorkerFrameWriter writer = new(stream, options);
|
||||
await writer.WriteAsync(original);
|
||||
stream.Position = 0;
|
||||
|
||||
WorkerFrameReader reader = new(stream, options);
|
||||
WorkerEnvelope parsed = await reader.ReadAsync();
|
||||
|
||||
Assert.Equal(original, parsed);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that reading a frame with partial reads reassembles the frame correctly.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user