perf(net): borrow inbound packet storage

Decode headers, optional fields, fragments, and single-fragment messages directly over pooled datagrams. Copy only fragment state that crosses a datagram lifetime, preserve synchronous dispatch and ACK ordering, and lock the path to the owned decoder with differential and zero-allocation tests.
This commit is contained in:
Erik 2026-07-25 05:58:55 +02:00
parent 7211bb1bf7
commit e928c5dd02
18 changed files with 1329 additions and 66 deletions

View file

@ -143,9 +143,9 @@ public static class TurbineChat
/// for any structural error (truncation, unknown blob_type, ACE
/// id-mismatch in RequestSendToRoomById, malformed UTF-16 string).
/// </summary>
public static Parsed? TryParse(byte[] body)
public static Parsed? TryParse(ReadOnlySpan<byte> body)
{
if (body is null || body.Length < 4 + HeaderSize) return null;
if (body.Length < 4 + HeaderSize) return null;
uint opcode = BinaryPrimitives.ReadUInt32LittleEndian(body);
if (opcode != Opcode) return null;
@ -259,7 +259,7 @@ public static class TurbineChat
int remaining = expectedPayload;
if (body.Length - pos < remaining) return null;
var bytes = new byte[remaining];
Array.Copy(body, pos, bytes, 0, remaining);
body.Slice(pos, remaining).CopyTo(bytes);
pos += remaining;
payload = new Payload.Unknown(bytes);
break;
@ -403,7 +403,9 @@ public static class TurbineChat
/// the high bit of the first byte is set the prefix is two bytes
/// (high 7 bits of byte 0 + all 8 bits of byte 1).
/// </summary>
public static string ReadTurbineString(byte[] data, ref int pos)
public static string ReadTurbineString(
ReadOnlySpan<byte> data,
ref int pos)
{
if (data.Length - pos < 1) throw new FormatException("turbine str: truncated len");
int chars = data[pos];
@ -422,7 +424,8 @@ public static class TurbineChat
// String.from_utf16 in Rust validates surrogate pairs; .NET's
// Encoding.Unicode.GetString matches that semantics.
string s = Encoding.Unicode.GetString(data, pos, (int)bytesLen);
string s = Encoding.Unicode.GetString(
data.Slice(pos, (int)bytesLen));
pos += (int)bytesLen;
return s;
}
@ -463,9 +466,12 @@ public static class TurbineChat
// Helpers
// ──────────────────────────────────────────────────────────────
private static uint ReadU32(byte[] data, ref int pos)
private static uint ReadU32(
ReadOnlySpan<byte> data,
ref int pos)
{
uint v = BinaryPrimitives.ReadUInt32LittleEndian(data.AsSpan(pos, 4));
uint v = BinaryPrimitives.ReadUInt32LittleEndian(
data.Slice(pos, 4));
pos += 4;
return v;
}