Skip to content
Configuration Reference

Configuration Reference

Complete reference for all configuration types in zerg.

EngineOptions

Top-level configuration passed to new Engine(options).

public class EngineOptions
{
    public int ReactorCount { get; init; } = 1;
    public string Ip { get; init; } = "0.0.0.0";
    public ushort Port { get; init; } = 8080;
    public int Backlog { get; init; } = 65535;
    public AcceptorConfig AcceptorConfig { get; init; } = new();
    public ReactorConfig[] ReactorConfigs { get; set; } = null!;
}
PropertyTypeDefaultDescription
ReactorCountint1Number of reactor event-loop threads. Each gets its own io_uring.
Ipstring"0.0.0.0"Bind address. "0.0.0.0" for all IPv4, "::" for all IPv6.
Portushort8080TCP listen port.
Backlogint65535Kernel listen backlog (pending connection queue size).
AcceptorConfigAcceptorConfignew()Acceptor ring configuration.
ReactorConfigsReactorConfig[]nullPer-reactor configs. Auto-filled with defaults if null.

ReactorConfig

Per-reactor configuration. Sealed record with default values.

public sealed record ReactorConfig(
    uint RingFlags = IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN,
    int SqCpuThread = -1,
    uint SqThreadIdleMs = 100,
    uint RingEntries = 8 * 1024,
    int RecvBufferSize = 32 * 1024,
    int BufferRingEntries = 16 * 1024,
    int BatchCqes = 4096,
    int MaxConnectionsPerReactor = 8 * 1024,
    long CqTimeout = 1_000_000
);
PropertyTypeDefaultDescription
RingFlagsuintSINGLE_ISSUER | DEFER_TASKRUNio_uring setup flags. Controls kernel behavior.
SqCpuThreadint-1CPU core for SQPOLL thread. -1 = kernel decides. Only with SQPOLL.
SqThreadIdleMsuint100SQPOLL idle timeout (ms) before kernel thread sleeps.
RingEntriesuint8192SQ/CQ ring size. Max in-flight I/O operations.
RecvBufferSizeint32768Bytes per receive buffer. Larger = fewer buffers for big payloads.
BufferRingEntriesint16384Number of recv buffers in buffer ring. Must be power of 2.
BatchCqesint4096Max CQEs processed per event loop iteration.
MaxConnectionsPerReactorint8192Connection limit per reactor. Should be <= RingEntries.
CqTimeoutlong1000000Wait timeout in nanoseconds (1 ms). Lower = lower latency, more CPU.

AcceptorConfig

Acceptor thread configuration. Sealed record with default values.

public sealed record AcceptorConfig(
    uint RingFlags = 0,
    int SqCpuThread = -1,
    uint SqThreadIdleMs = 100,
    uint RingEntries = 8 * 1024,
    uint BatchSqes = 4096,
    long CqTimeout = 100_000_000,
    IPVersion IPVersion = IPVersion.IPv6DualStack
);
PropertyTypeDefaultDescription
RingFlagsuint0io_uring setup flags for the acceptor ring.
SqCpuThreadint-1CPU core for SQPOLL thread.
SqThreadIdleMsuint100SQPOLL idle timeout (ms).
RingEntriesuint8192SQ/CQ size. Bounds accept CQE burst capacity.
BatchSqesuint4096Max accept completions per loop iteration.
CqTimeoutlong100000000Wait timeout in ns (100 ms). Higher than reactor since accepts are bursty.
IPVersionIPVersionIPv6DualStackIP stack for the listening socket.

IPVersion

public enum IPVersion
{
    IPv4Only,
    IPv6DualStack
}
ValueSocketDescription
IPv4OnlyAF_INETIPv4 only.
IPv6DualStackAF_INET6 (V6ONLY=0)Accepts both IPv4 and IPv6. IPv4 clients appear as ::ffff:a.b.c.d.

io_uring Setup Flags

Available constants from the ABI class for use in RingFlags:

FlagValueDescription
IORING_SETUP_IOPOLL1 << 0Polling-based I/O (not recommended for sockets).
IORING_SETUP_SQPOLL1 << 1Kernel thread polls SQ. Eliminates submit syscall.
IORING_SETUP_SQ_AFF1 << 2Pin SQPOLL thread to SqCpuThread.
IORING_SETUP_CQSIZE1 << 3Custom CQ size (separate from SQ).
IORING_SETUP_CLAMP1 << 4Clamp queue sizes to kernel limits.
IORING_SETUP_SINGLE_ISSUER1 << 12Single thread submits. Reduces kernel locking.
IORING_SETUP_DEFER_TASKRUN1 << 13Defer task_work. Reduces latency spikes.
IORING_SETUP_NO_MMAP1 << 14Don’t mmap rings (use registered buffers).
IORING_SETUP_REGISTERED_FD_ONLY1 << 15Only allow registered file descriptors.

Configuration Examples

High-Throughput Server

var engine = new Engine(new EngineOptions
{
    Port = 8080,
    ReactorCount = Environment.ProcessorCount,
    ReactorConfigs = Enumerable.Range(0, Environment.ProcessorCount)
        .Select(_ => new ReactorConfig(
            RingEntries: 16384,
            RecvBufferSize: 64 * 1024,
            BufferRingEntries: 32 * 1024,
            BatchCqes: 8192,
            MaxConnectionsPerReactor: 16384,
            CqTimeout: 500_000  // 0.5 ms
        )).ToArray()
});

Low-Latency Server with SQPOLL

var engine = new Engine(new EngineOptions
{
    Port = 8080,
    ReactorCount = 4,
    ReactorConfigs = Enumerable.Range(0, 4)
        .Select(i => new ReactorConfig(
            RingFlags: ABI.IORING_SETUP_SQPOLL
                     | ABI.IORING_SETUP_SQ_AFF
                     | ABI.IORING_SETUP_SINGLE_ISSUER,
            SqCpuThread: i + 4,      // pin SQPOLL threads to CPUs 4-7
            SqThreadIdleMs: 200,
            CqTimeout: 100_000        // 0.1 ms
        )).ToArray()
});

Minimal Memory Footprint

var engine = new Engine(new EngineOptions
{
    Port = 8080,
    ReactorCount = 1,
    ReactorConfigs = [new ReactorConfig(
        RecvBufferSize: 4096,
        BufferRingEntries: 1024,
        MaxConnectionsPerReactor: 256,
        RingEntries: 512
    )]
});