Skip to content

Feature: Packet Back‐Pressure

Tsu edited this page Jun 5, 2026 · 2 revisions

This feature puts hard budgets around packet enqueue and main-thread dispatch.

What It Does

StratumPacketBackPressure protects ClientPackets with four constraints:

  • max queued packets per client at enqueue time
  • max wall-clock time per tick
  • max packets per client per tick
  • deferred packet requeueing when a client hits its per-tick dispatch cap

The point is fairness and tick stability, not max throughput at any cost.

Config Surface

StratumPacketBackPressureConfig:

public bool Enabled { get; set; } = true;
public int MaxMillisecondsPerTick { get; set; } = 25;
public int MaxPacketsPerClientPerTick { get; set; } = 32;
public int MaxQueueDepthPerClient { get; set; } = 2000;
public bool KickOnQueueOverflow { get; set; } = true;
public string KickMessage { get; set; } = "Disconnected by Stratum packet back-pressure";

Enqueue Guard

ServerMain calls TryRegisterEnqueue(...) for new connections, disconnects, and parsed client packets before putting them on ClientPackets.

if (StratumRuntime.PacketBackPressure.TryRegisterEnqueue(item, out string disconnectReason))
{
    ClientPackets.Enqueue(item);
    return;
}

That records per-client queue depth immediately, so a flooding client cannot hide behind a slow main-thread drain. If the depth crosses MaxQueueDepthPerClient, Stratum rejects that packet at enqueue time and queues a disconnect packet instead.

Core Drain Logic

From StratumPacketBackPressure.DrainAndDispatch(...), dispatch still respects wall-clock and per-client caps:

long start = Stopwatch.GetTimestamp();
long budgetTicks = (long)maxMs * ticksPerMs;

while (true)
{
    if (Stopwatch.GetTimestamp() - start >= budgetTicks) break;
    if (!source.TryDequeue(out ReceivedClientPacket pkt)) break;

    servedThisTick.TryGetValue(cid, out int served);
    if (served >= perClientCap)
    {
        deferred.Add(pkt);
        continue;
    }

    dispatch(pkt);
    MarkPacketFinished(pkt);
    dispatched++;
    servedThisTick[cid] = served + 1;
}

Deferred packets are requeued for the next tick:

for (int i = 0; i < deferredCount; i++)
{
    source.Enqueue(deferred[i]);
}

Kick Behavior

If queue overflow kicking is enabled and a client's tracked queue depth crosses the threshold, the enqueue guard rejects that packet and schedules a disconnect packet with KickMessage.

if (queued > queueKick)
{
    totalRejectedAtEnqueue++;
    disconnectReason = bp.KickOnQueueOverflow ? bp.KickMessage : null;
    return false;
}

Integration Point

ServerMain uses EnqueueStratumClientPacket(...) for enqueue-time accounting and StratumRuntime.PacketBackPressure.DrainAndDispatch(...) instead of unbounded queue drain.

Runtime Report

The packet report includes enqueue rejections and queue-depth telemetry:

rejectedAtEnqueue=...
queueDepth=...
peakQueueDepth=...

Source of Truth

  • sources/VintagestoryLib/Vintagestory.Server/StratumPacketBackPressure.cs
  • sources/VintagestoryLib/Vintagestory.Server/StratumConfig.cs (StratumPacketBackPressureConfig)
  • patches/VintagestoryLib/Vintagestory.Server/ServerMain.cs.patch

Clone this wiki locally