Merge fix/c3-tracker-hygiene: GWC-31 perf-pass comments relabeled PERF-nn, archreview prefixes reserved in REVIEW-PROCESS.md, cycle-1/2 tracker housekeeping (GWC-16 Won't fix, IPC-08/IPC-31 Done, TST-06/17 refreshed, WRK-29..31 reserved)
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (push) Successful in 1m57s
ci / java (push) Successful in 2m11s
ci / portable (push) Successful in 9m23s

This commit is contained in:
Joseph Doherty
2026-08-20 09:40:05 -04:00
18 changed files with 65 additions and 27 deletions
@@ -20,7 +20,7 @@ public sealed class WorkerFrameReader
private readonly WorkerFrameProtocolOptions _options;
private readonly Stream _stream;
// Reused across frames rather than allocated per read (GWC-30). Safe because ReadAsync is
// Reused across frames rather than allocated per read (PERF-22). Safe because ReadAsync is
// single-consumer by construction; the prefix is fully overwritten by every read.
//
// The single-consumer invariant has to survive teardown as well as steady state, because a read
@@ -668,10 +668,10 @@ public sealed class WorkerFrameWriter
// Serialize once into a single pooled buffer that carries the 4-byte length prefix followed
// by the payload, then issue one stream write. This avoids a second serialization pass, a
// separate prefix array, a separate prefix write, and any per-frame heap allocation — the
// gateway-side writer's GWC-30 shape, now matched on the net48 side. The rented buffer may
// be larger than requested, so only the first frameLength bytes are ever written. The buffer
// is returned only after this frame's write has completed; the batch flush deferred to the
// end of the drain (see DrainQueuedFramesAsync) does not read from it.
// gateway-side writer's pooled-buffer shape (PERF-22), now matched on the net48 side. The
// rented buffer may be larger than requested, so only the first frameLength bytes are ever
// written. The buffer is returned only after this frame's write has completed; the batch
// flush deferred to the end of the drain (see DrainQueuedFramesAsync) does not read from it.
int frameLength = sizeof(uint) + payloadLength;
byte[] frame = ArrayPool<byte>.Shared.Rent(frameLength);
try