Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frameworks/zix-http3/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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 ;; \
Expand All @@ -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

Expand Down
70 changes: 1 addition & 69 deletions frameworks/zix-http3/src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -23,73 +23,13 @@ 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";
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 {
Expand All @@ -109,7 +49,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();
Expand All @@ -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();
Expand Down
28 changes: 14 additions & 14 deletions site/data/results/zix.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,18 @@
"baseline-h3-64": {
"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
Expand Down Expand Up @@ -218,18 +218,18 @@
"static-h3-64": {
"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
Expand Down