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

@ -17,7 +17,10 @@ namespace AcDream.Core.Net.Messages;
/// Handlers are invoked synchronously on the thread that called
/// <see cref="Dispatch"/> — normally the render thread since
/// <see cref="WorldSession"/>'s decode path runs there in the current
/// architecture. Handlers must not block.
/// architecture. Handlers must not block or retain the envelope/payload:
/// production payload memory borrows a pooled inbound datagram and expires
/// when the synchronous dispatch call returns. Handlers must parse or copy
/// any state they need to keep.
/// </para>
/// </summary>
public sealed class GameEventDispatcher
@ -86,7 +89,8 @@ public sealed class GameEventDispatcher
/// <summary>
/// Route an envelope to its handler, or log as unhandled. Exceptions
/// inside handlers are swallowed to keep the decode loop alive — a
/// malformed event from the server should not crash the client.
/// malformed event from the server should not crash the client. The
/// handler must not retain <paramref name="envelope"/> or its payload.
/// </summary>
public void Dispatch(GameEventEnvelope envelope)
{