From 97ca18cecfab17da707a3c209ba3498e58d9c5ef Mon Sep 17 00:00:00 2001 From: prothegee Date: Mon, 13 Jul 2026 18:35:52 +0700 Subject: [PATCH 1/4] fully fledged with URING --- frameworks/zix-http3/src/main.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/zix-http3/src/main.zig b/frameworks/zix-http3/src/main.zig index 8ee95fc8e..240f02cfd 100644 --- a/frameworks/zix-http3/src/main.zig +++ b/frameworks/zix-http3/src/main.zig @@ -109,7 +109,7 @@ fn probeServer(io: std.Io, tls: *zix.Tls.Context) void { .ip = IP, .port = PROBE_TCP_PORT, .tls = tls, - .dispatch_model = .EPOLL, + .dispatch_model = DISPATCH_MODEL, .workers = 1, }); defer server.deinit(); From edfadb1775eb66e2f33656c1f3c4aa41d40f4645 Mon Sep 17 00:00:00 2001 From: prothegee Date: Mon, 13 Jul 2026 20:15:27 +0700 Subject: [PATCH 2/4] realign workdir --- frameworks/zix-http3/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/zix-http3/Dockerfile b/frameworks/zix-http3/Dockerfile index 661e75e4f..53dd98715 100644 --- a/frameworks/zix-http3/Dockerfile +++ b/frameworks/zix-http3/Dockerfile @@ -9,6 +9,7 @@ ARG ZIG_VERSION=0.16.0 ARG ZIX_VERSION=0.5.x-rc1 RUN apk add --no-cache ca-certificates curl git tar xz openssl +WORKDIR /server RUN set -eu; \ case "${TARGETARCH:-amd64}" in \ amd64) ZIG_ARCH=x86_64 ;; \ @@ -20,7 +21,6 @@ RUN set -eu; \ mv "/opt/zig-${ZIG_ARCH}-linux-${ZIG_VERSION}" /opt/zig ENV PATH="/opt/zig:${PATH}" -WORKDIR /server COPY build.zig build.zig.zon ./ COPY src ./src From 567fdb5f9fc0fd1bb906789683471ac9f6aa3bf8 Mon Sep 17 00:00:00 2001 From: prothegee Date: Wed, 15 Jul 2026 01:55:01 +0700 Subject: [PATCH 3/4] remove prewarm --- frameworks/zix-http3/src/main.zig | 68 ------------------------------- 1 file changed, 68 deletions(-) diff --git a/frameworks/zix-http3/src/main.zig b/frameworks/zix-http3/src/main.zig index 240f02cfd..623c3ceea 100644 --- a/frameworks/zix-http3/src/main.zig +++ b/frameworks/zix-http3/src/main.zig @@ -23,8 +23,6 @@ const DISPATCH_MODEL: zix.Http3.DispatchModel = .URING; const WORKERS: usize = 0; -// Same number as PORT on purpose: QUIC binds UDP 8443, the readiness probe -// arrives on TCP 8443 (the two coexist, distinct sockets). const PROBE_TCP_PORT: u16 = 8443; const TLS_CERT_DEFAULT: []const u8 = "/etc/zix-tls/server.crt"; @@ -32,64 +30,6 @@ const TLS_KEY_DEFAULT: []const u8 = "/etc/zix-tls/server.key"; // --------------------------------------------------------- // -/// Populate the static cache once at startup, -/// single-threaded, warming every candidate the handler probes (.br, .gz, identity) -/// so the request path only hits the lock-free lookup. -/// Without it the first request for each name inserts -/// under the spinlock while opening the file. -fn prewarmStatic() void { - var base_buf: [512]u8 = undefined; - var base = handler.g_static_base; - if (base.len > 1 and base[base.len - 1] == '/') base = base[0 .. base.len - 1]; - if (base.len >= base_buf.len) return; - - @memcpy(base_buf[0..base.len], base); - base_buf[base.len] = 0; - - const dir_fd = std.posix.openatZ(std.posix.AT.FDCWD, @ptrCast(&base_buf), .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, 0) catch return; - defer _ = std.posix.system.close(dir_fd); - - // Iterate with raw getdents64 (this std.fs has no portable Dir.iterate). - // linux_dirent64 layout: - // d_ino(8) d_off(8) d_reclen(2 @16) d_type(1 @18) d_name(@19, null-terminated). - var dbuf: [4096]u8 = undefined; - while (true) { - const rc = std.os.linux.getdents64(dir_fd, &dbuf, dbuf.len); - const got: isize = @bitCast(rc); - if (got <= 0) break; - - var off: usize = 0; - while (off < @as(usize, @intCast(got))) { - const reclen: usize = @as(usize, dbuf[off + 16]) | (@as(usize, dbuf[off + 17]) << 8); - const d_type = dbuf[off + 18]; - const name = std.mem.sliceTo(dbuf[off + 19 ..], 0); - off += reclen; - - if (d_type == 4) continue; // DT_DIR - if (name.len == 0 or name[0] == '.') continue; - - // Reduce a precompressed name to its base, - // then warm every candidate (.br, .gz, identity). - // A missing variant caches a null slot, - // so the request path never inserts under load. - var stem = name; - if (std.mem.endsWith(u8, stem, ".br")) stem = stem[0 .. stem.len - ".br".len] else if (std.mem.endsWith(u8, stem, ".gz")) stem = stem[0 .. stem.len - ".gz".len]; - if (stem.len == 0 or stem.len > handler.STATIC_NAME_MAX) continue; - - var cand_buf: [handler.STATIC_NAME_MAX + 3]u8 = undefined; - if (std.fmt.bufPrint(&cand_buf, "{s}.br", .{stem})) |c| { - _ = handler.resolveStatic(c); - } else |_| {} - if (std.fmt.bufPrint(&cand_buf, "{s}.gz", .{stem})) |c| { - _ = handler.resolveStatic(c); - } else |_| {} - _ = handler.resolveStatic(stem); - } - } -} - -// --------------------------------------------------------- // - // Answers the readiness probe (GET /baseline2?a=1&b=1 over TCP https). // Any 2xx body satisfies the probe curl, the value mirrors a=1&b=1. fn probeResponder(_: *const zix.Http1.ParsedHead, _: []const u8, fd: std.posix.fd_t) void { @@ -125,16 +65,8 @@ const Routes = zix.Http3.Router(&[_]zix.Http3.Route{ }); pub fn main(process: std.process.Init) !void { - // Elevate scheduling priority (setpriority -19). Fails silently when the - // process lacks CAP_SYS_NICE, so no special capability is required for correctness. - _ = std.os.linux.syscall3(.setpriority, 0, 0, @as(usize, @bitCast(@as(isize, -19)))); - - // Warm the static cache before any worker serves, - // so the request path is lock-free (no spinlock - // held across a file open on the first request for each name). const data_dir = "/data"; handler.g_static_base = std.fmt.bufPrint(&handler.g_static_base_buf, "{s}/static/", .{data_dir}) catch "/data/static/"; - prewarmStatic(); var allocator_tls = std.heap.ArenaAllocator.init(std.heap.smp_allocator); defer allocator_tls.deinit(); From c37b8c084f438e3bb718dec0107723a2a2d8b9ea Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 04:36:02 +0000 Subject: [PATCH 4/4] Benchmark results: zix-http3 --- site/data/baseline-h3-64.json | 14 +++++++------- site/data/frameworks.json | 7 +++++++ site/data/static-h3-64.json | 14 +++++++------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/site/data/baseline-h3-64.json b/site/data/baseline-h3-64.json index 6894b64cd..4c00de7bc 100644 --- a/site/data/baseline-h3-64.json +++ b/site/data/baseline-h3-64.json @@ -253,18 +253,18 @@ { "framework": "zix", "language": "Zig", - "rps": 9573685, - "avg_latency": "413us", - "p99_latency": "757us", - "cpu": "1283.3%", - "memory": "416MiB", + "rps": 9392865, + "avg_latency": "420us", + "p99_latency": "766us", + "cpu": "1282.4%", + "memory": "413MiB", "connections": 64, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "73.19MB/s", + "bandwidth": "71.95MB/s", "reconnects": 0, - "status_2xx": 47964164, + "status_2xx": 47152183, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/frameworks.json b/site/data/frameworks.json index 95e349962..ceedbed1d 100644 --- a/site/data/frameworks.json +++ b/site/data/frameworks.json @@ -1016,6 +1016,13 @@ "type": "engine", "engine": "zix", "variants": [ + { + "dir": "zix-http2", + "description": "Zig HTTP/2 server on the zix.Http2 raw engine, .URING dispatch: shared-nothing per-core io_uring with SO_REUSEPORT, per-worker stream-slot pool. Dual listener (config.tls_port): h2c 8082 plus h2 over TLS 1.3 (ALPN h2) on 8443, one process.", + "repo": "https://github.com/prothegee/zix", + "type": "engine", + "engine": "zix.Http2 URING Dispatch Model" + }, { "dir": "zix-http3", "description": "Zig HTTP/3 server on the zix.Http3 engine, pure-Zig QUIC on std.crypto (RFC 9000/9001/9002/9114), .URING dispatch: one SO_REUSEPORT worker per core on UDP 8443, NewReno with PTO retransmit, rolling MAX_STREAMS/MAX_DATA credit. A one-worker https responder on TCP 8443 answers the readiness probe, idle during the run.", diff --git a/site/data/static-h3-64.json b/site/data/static-h3-64.json index 75b68792c..071180e96 100644 --- a/site/data/static-h3-64.json +++ b/site/data/static-h3-64.json @@ -253,18 +253,18 @@ { "framework": "zix", "language": "Zig", - "rps": 611890, - "avg_latency": "3.31ms", - "p99_latency": "10.22ms", - "cpu": "2905.3%", - "memory": "403MiB", + "rps": 686550, + "avg_latency": "4.24ms", + "p99_latency": "18.10ms", + "cpu": "3343.4%", + "memory": "415MiB", "connections": 64, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "9.29GB/s", + "bandwidth": "10.45GB/s", "reconnects": 0, - "status_2xx": 3065571, + "status_2xx": 3446483, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0