diff --git a/frameworks/zix/Dockerfile b/frameworks/zix/Dockerfile index 380552a68..692929f64 100644 --- a/frameworks/zix/Dockerfile +++ b/frameworks/zix/Dockerfile @@ -5,7 +5,7 @@ ARG RETRY=6 ARG TARGETARCH ARG RETRY_DELAY=3 ARG ZIG_VERSION=0.16.0 -ARG ZIX_VERSION=0.4.x +ARG ZIX_VERSION=0.4.x-rc3 RUN apk add --no-cache ca-certificates curl git tar xz RUN set -eu; \ @@ -19,9 +19,9 @@ RUN set -eu; \ mv "/opt/zig-${ZIG_ARCH}-linux-${ZIG_VERSION}" /opt/zig ENV PATH="/opt/zig:${PATH}" -# Vendor zix 0.4.x, separate layer so source-only rebuilds skip the fetch. +# Vendor zix X.Y.Z, separate layer so source-only rebuilds skip the fetch. # The Http1 raw engine work this image needs (large-body drain plus the per-worker -# response cache used by the /json endpoint) must be present on the 0.4.x branch. +# response cache used by the /json endpoint) must be present on the X.Y.Z branch. # Four ordered attempts before giving up: curl the archive tarball from github then # codeberg, then a shallow git clone from github then codeberg. The github archive # redirects to codeload.github.com (which the benchmark runner may not resolve), so diff --git a/frameworks/zix/meta.json b/frameworks/zix/meta.json index e1f44d26d..b031b6910 100644 --- a/frameworks/zix/meta.json +++ b/frameworks/zix/meta.json @@ -3,7 +3,7 @@ "language": "Zig", "type": "engine", "engine": "zix", - "description": "Zig HTTP/1.1 server on the zix.Http1 raw engine (no std.http). Shared-nothing: each worker runs its own SO_REUSEPORT accept plus level-triggered epoll loop and owns its connections. The /json endpoint serves from the per-worker response cache, and request bodies larger than the read buffer are drained rather than buffered.", + "description": "Zig HTTP/1.1 server on the zix.Http1 raw engine (no std.http). Shared-nothing: each worker runs its own SO_REUSEPORT multishot accept plus io_uring completion loop and owns its connections. The /json endpoint serves from the per-worker response cache, and request bodies larger than the read buffer are drained rather than buffered.", "repo": "https://github.com/prothegee/zix", "enabled": true, "tests": [ diff --git a/frameworks/zix/src/dataset.zig b/frameworks/zix/src/dataset.zig index 9b0b8999e..4d12be803 100644 --- a/frameworks/zix/src/dataset.zig +++ b/frameworks/zix/src/dataset.zig @@ -1,5 +1,4 @@ //! HttpArena: zix -//! zix version: 0.4.x //! //! Dataset loader for the /json endpoint. //! diff --git a/frameworks/zix/src/main.zig b/frameworks/zix/src/main.zig index 093e37c91..90fe1bd22 100644 --- a/frameworks/zix/src/main.zig +++ b/frameworks/zix/src/main.zig @@ -1,13 +1,12 @@ //! HttpArena: zix -//! zix version: 0.4.x //! //! zix HttpArena HTTP/1.1 entry point. //! -//! Intent: demonstrate zix.Http1 (URING dispatch model) against the HttpArena +//! Intent: demonstrate zix.Http1 (EPOLL dispatch model) against the HttpArena //! HTTP/1.1 benchmark suite (baseline, pipelined, short-lived). //! //! Design choices: -//! - rawIntercept: called before any header parsing for each URING request. +//! - rawIntercept: called before any header parsing for each EPOLL request. //! Handles /pipeline with zero parse overhead (direct byte-match + sink write), //! direct byte-match before any parsing, avoiding the header scan loop. Routes that fall //! through are handled by the Router dispatch with full parsing. @@ -23,14 +22,25 @@ const dataset = @import("dataset.zig"); const PORT: u16 = 8080; const LISTEN_IP: []const u8 = "::"; -const DISPATCH_MODEL: zix.Http1.DispatchModel = .EPOLL; +const DISPATCH_MODEL: zix.Http1.DispatchModel = .URING; const KERNEL_BACKLOG: u31 = 16 * 1024; -/// 4 KiB per-connection recv buffer (heap-allocated once at accept time). -/// Benchmark requests are under 300 bytes. Halving from 16 KiB cuts the -/// working set from 64 MiB to 16 MiB at 4096c, reducing cache pressure. -/// Large upload bodies are drained by the engine in chunks, so headers -/// (always < 4 KiB) are the only part that needs to fit. -const MAX_RECV_BUF: usize = 4 * 1024; +/// Per-machine tuning profile (ADR-041 increment 5). The dev box is 12 threads +/// / 32 GB (lean, memory-bound), the competition box is 64 cores / 251 GB +/// (throughput, RAM-abundant). Only the recv buffer differs: workers auto-scale +/// (WORKERS = 0), and the backlog and cache are already sized for both. Select +/// .throughput for the 64-core deployment. +const Profile = enum { lean, throughput }; +const PROFILE: Profile = .lean; + +/// Per-connection recv buffer, heap-allocated once at accept time. .lean keeps +/// 4 KiB to hold the working set small (benchmark requests are under 300 bytes, +/// and large upload bodies are drained by the engine in chunks, so only headers, +/// always < 4 KiB, must fit). .throughput raises it to 16 KiB for deeper +/// pipelined batches per recv, which the RAM-abundant box absorbs. +const MAX_RECV_BUF: usize = switch (PROFILE) { + .lean => 4 * 1024, + .throughput => 16 * 1024, +}; const MAX_HEADERS: u8 = 16; const WORKERS: usize = 0; @@ -99,7 +109,7 @@ fn pipelineHandler(head: *const zix.Http1.ParsedHead, body: []const u8, fd: std. zix.Http1.fdWriteAll(fd, PIPELINE_RESP) catch {}; } -// Raw-request interceptor for the URING dispatch model. Called before any header +// Raw-request interceptor for the EPOLL dispatch model. Called before any header // parsing on each inbound request. Handles /pipeline with zero parse overhead: // byte-matches the path directly on rem, then appends PIPELINE_RESP to the // coalescing RespSink. Unknown diff --git a/site/data/baseline-4096.json b/site/data/baseline-4096.json index 9e745ccb9..f55cc9a2d 100644 --- a/site/data/baseline-4096.json +++ b/site/data/baseline-4096.json @@ -1627,19 +1627,19 @@ { "framework": "zix", "language": "Zig", - "rps": 3654683, - "avg_latency": "1.12ms", - "p99_latency": "2.36ms", - "cpu": "6610.8%", - "memory": "395MiB", + "rps": 4492613, + "avg_latency": "911us", + "p99_latency": "1.19ms", + "cpu": "6413.1%", + "memory": "186MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "229.97MB/s", - "input_bw": "282.32MB/s", + "bandwidth": "282.68MB/s", + "input_bw": "347.04MB/s", "reconnects": 0, - "status_2xx": 18273419, + "status_2xx": 22463065, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/baseline-512.json b/site/data/baseline-512.json index b33c30c49..21f63b8ee 100644 --- a/site/data/baseline-512.json +++ b/site/data/baseline-512.json @@ -1627,19 +1627,19 @@ { "framework": "zix", "language": "Zig", - "rps": 3670251, - "avg_latency": "138us", - "p99_latency": "371us", - "cpu": "6426.7%", - "memory": "342MiB", + "rps": 4217982, + "avg_latency": "120us", + "p99_latency": "231us", + "cpu": "6348.6%", + "memory": "130MiB", "connections": 512, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "230.95MB/s", - "input_bw": "283.52MB/s", + "bandwidth": "265.42MB/s", + "input_bw": "325.83MB/s", "reconnects": 0, - "status_2xx": 18351256, + "status_2xx": 21089911, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/frameworks.json b/site/data/frameworks.json index 6aa6c75da..6ae2d0cb5 100644 --- a/site/data/frameworks.json +++ b/site/data/frameworks.json @@ -915,7 +915,7 @@ }, "zix": { "dir": "zix", - "description": "Zig HTTP/1.1 server on the zix.Http1 raw engine (no std.http). Shared-nothing: each worker runs its own SO_REUSEPORT accept plus level-triggered epoll loop and owns its connections. The /json endpoint serves from the per-worker response cache, and request bodies larger than the read buffer are drained rather than buffered.", + "description": "Zig HTTP/1.1 server on the zix.Http1 raw engine (no std.http). Shared-nothing: each worker runs its own SO_REUSEPORT multishot accept plus io_uring completion loop and owns its connections. The /json endpoint serves from the per-worker response cache, and request bodies larger than the read buffer are drained rather than buffered.", "repo": "https://github.com/prothegee/zix", "type": "engine", "engine": "zix" diff --git a/site/data/json-4096.json b/site/data/json-4096.json index c4903c76d..85aae891e 100644 --- a/site/data/json-4096.json +++ b/site/data/json-4096.json @@ -1375,19 +1375,19 @@ { "framework": "zix", "language": "Zig", - "rps": 2396373, - "avg_latency": "865us", - "p99_latency": "3.70ms", - "cpu": "6464.5%", - "memory": "1.2GiB", + "rps": 2348626, + "avg_latency": "614us", + "p99_latency": "2.75ms", + "cpu": "5365.1%", + "memory": "290MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "8.02GB/s", - "input_bw": "114.27MB/s", - "reconnects": 478596, - "status_2xx": 11981868, + "bandwidth": "7.86GB/s", + "input_bw": "111.99MB/s", + "reconnects": 468990, + "status_2xx": 11743130, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/limited-conn-4096.json b/site/data/limited-conn-4096.json index 4a7bc63de..ea98cd9ee 100644 --- a/site/data/limited-conn-4096.json +++ b/site/data/limited-conn-4096.json @@ -1627,19 +1627,19 @@ { "framework": "zix", "language": "Zig", - "rps": 2748274, - "avg_latency": "1.38ms", - "p99_latency": "2.75ms", - "cpu": "6224.6%", - "memory": "1.5GiB", + "rps": 2751069, + "avg_latency": "1.35ms", + "p99_latency": "1.89ms", + "cpu": "5783.9%", + "memory": "237MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "172.91MB/s", - "input_bw": "212.30MB/s", - "reconnects": 1374498, - "status_2xx": 13741371, + "bandwidth": "173.09MB/s", + "input_bw": "212.51MB/s", + "reconnects": 1375655, + "status_2xx": 13755345, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/limited-conn-512.json b/site/data/limited-conn-512.json index 8f33957dc..580b731e3 100644 --- a/site/data/limited-conn-512.json +++ b/site/data/limited-conn-512.json @@ -1627,19 +1627,19 @@ { "framework": "zix", "language": "Zig", - "rps": 2535229, - "avg_latency": "187us", - "p99_latency": "687us", - "cpu": "5722.1%", - "memory": "482MiB", + "rps": 2740199, + "avg_latency": "170us", + "p99_latency": "403us", + "cpu": "5474.7%", + "memory": "150MiB", "connections": 512, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "159.53MB/s", - "input_bw": "195.84MB/s", - "reconnects": 1267619, - "status_2xx": 12676149, + "bandwidth": "172.36MB/s", + "input_bw": "211.67MB/s", + "reconnects": 1369714, + "status_2xx": 13700995, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/pipelined-4096.json b/site/data/pipelined-4096.json index 4ca6975e5..a3a21860d 100644 --- a/site/data/pipelined-4096.json +++ b/site/data/pipelined-4096.json @@ -1598,18 +1598,18 @@ { "framework": "zix", "language": "Zig", - "rps": 49553494, - "avg_latency": "1.32ms", - "p99_latency": "2.80ms", - "cpu": "6562.4%", - "memory": "396MiB", + "rps": 55979164, + "avg_latency": "1.17ms", + "p99_latency": "1.79ms", + "cpu": "6454.4%", + "memory": "186MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 16, - "bandwidth": "3.04GB/s", + "bandwidth": "3.44GB/s", "reconnects": 0, - "status_2xx": 247767474, + "status_2xx": 279895824, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/pipelined-512.json b/site/data/pipelined-512.json index fd782d457..8284542a7 100644 --- a/site/data/pipelined-512.json +++ b/site/data/pipelined-512.json @@ -1598,18 +1598,18 @@ { "framework": "zix", "language": "Zig", - "rps": 49538550, - "avg_latency": "164us", - "p99_latency": "457us", - "cpu": "6412.0%", - "memory": "341MiB", + "rps": 53609380, + "avg_latency": "152us", + "p99_latency": "344us", + "cpu": "6399.9%", + "memory": "134MiB", "connections": 512, "threads": 64, "duration": "5s", "pipeline": 16, - "bandwidth": "3.04GB/s", + "bandwidth": "3.29GB/s", "reconnects": 0, - "status_2xx": 247692752, + "status_2xx": 268046903, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/static-1024.json b/site/data/static-1024.json index f669a94b4..acbb53499 100644 --- a/site/data/static-1024.json +++ b/site/data/static-1024.json @@ -1255,18 +1255,18 @@ { "framework": "zix", "language": "Zig", - "rps": 2035469, - "avg_latency": "301.89us", - "p99_latency": "4.40ms", - "cpu": "5618.5%", - "memory": "351MiB", + "rps": 2025521, + "avg_latency": "300.92us", + "p99_latency": "3.21ms", + "cpu": "5488.4%", + "memory": "140MiB", "connections": 1024, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "31.01GB", + "bandwidth": "30.86GB", "reconnects": 0, - "status_2xx": 10380866, + "status_2xx": 10331115, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/static-4096.json b/site/data/static-4096.json index 812992aaf..03ed9c3c4 100644 --- a/site/data/static-4096.json +++ b/site/data/static-4096.json @@ -1255,18 +1255,18 @@ { "framework": "zix", "language": "Zig", - "rps": 2036430, - "avg_latency": "1.06ms", - "p99_latency": "5.02ms", - "cpu": "5600.2%", - "memory": "417MiB", + "rps": 2036680, + "avg_latency": "1.05ms", + "p99_latency": "7.16ms", + "cpu": "5503.2%", + "memory": "195MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "31.02GB", + "bandwidth": "31.03GB", "reconnects": 0, - "status_2xx": 10385893, + "status_2xx": 10386093, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/static-6800.json b/site/data/static-6800.json index 9eab3178b..b23eaf756 100644 --- a/site/data/static-6800.json +++ b/site/data/static-6800.json @@ -1255,18 +1255,18 @@ { "framework": "zix", "language": "Zig", - "rps": 1984205, - "avg_latency": "1.77ms", - "p99_latency": "8.72ms", - "cpu": "5282.5%", - "memory": "496MiB", + "rps": 1986456, + "avg_latency": "1.75ms", + "p99_latency": "5.18ms", + "cpu": "5269.1%", + "memory": "241MiB", "connections": 6800, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "30.23GB", + "bandwidth": "30.26GB", "reconnects": 0, - "status_2xx": 10104695, + "status_2xx": 10111205, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/upload-256.json b/site/data/upload-256.json index 9759686ff..8cc85c85b 100644 --- a/site/data/upload-256.json +++ b/site/data/upload-256.json @@ -1201,19 +1201,19 @@ { "framework": "zix", "language": "Zig", - "rps": 6701, - "avg_latency": "37.98ms", - "p99_latency": "44.40ms", - "cpu": "889.6%", - "memory": "380MiB", + "rps": 6661, + "avg_latency": "38.12ms", + "p99_latency": "45.10ms", + "cpu": "943.2%", + "memory": "130MiB", "connections": 256, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "466.17KB/s", - "input_bw": "53.15GB/s", - "reconnects": 6760, - "status_2xx": 33644, + "bandwidth": "463.46KB/s", + "input_bw": "52.83GB/s", + "reconnects": 6688, + "status_2xx": 33441, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/upload-32.json b/site/data/upload-32.json index da662a4e5..3c31ca373 100644 --- a/site/data/upload-32.json +++ b/site/data/upload-32.json @@ -1201,19 +1201,19 @@ { "framework": "zix", "language": "Zig", - "rps": 8390, - "avg_latency": "3.78ms", - "p99_latency": "10.70ms", - "cpu": "1060.2%", - "memory": "337MiB", + "rps": 8185, + "avg_latency": "3.88ms", + "p99_latency": "10.90ms", + "cpu": "1065.4%", + "memory": "124MiB", "connections": 32, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "584.22KB/s", - "input_bw": "66.55GB/s", - "reconnects": 8401, - "status_2xx": 42037, + "bandwidth": "569.93KB/s", + "input_bw": "64.92GB/s", + "reconnects": 8199, + "status_2xx": 41007, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0