Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
6f32118
adding gitignore
prothegee Jul 13, 2026
9e02a61
adjusting dockerfile
prothegee Jul 13, 2026
09f31f7
matching dockerfile output
prothegee Jul 13, 2026
cef2a0f
redefined engine and description
prothegee Jul 13, 2026
b828a6c
minimizing entry and add adjustment
prothegee Jul 13, 2026
813c4d5
spliting handler
prothegee Jul 13, 2026
2da26b2
adjusting dataset
prothegee Jul 13, 2026
38f8007
retrigger ci validate attempt 1
prothegee Jul 13, 2026
9237546
retrigger ci validate attempt 2
prothegee Jul 13, 2026
5356ca3
Merge remote-tracking branch 'origin/main' into zix-http1
prothegee Jul 15, 2026
77747df
adding new entries tests
prothegee Jul 15, 2026
e64b419
use main-drivers branch
prothegee Jul 15, 2026
85d6e4f
simplifying head comment
prothegee Jul 15, 2026
f65b5a4
refine minimal approach
prothegee Jul 15, 2026
bdc943e
adding crud, async-db, api-n handlers
prothegee Jul 15, 2026
2e511fe
crud cache implementation
prothegee Jul 15, 2026
27634cf
postgresql implementation
prothegee Jul 15, 2026
8fba2df
redis implementation
prothegee Jul 15, 2026
3907ccb
Merge remote-tracking branch 'origin/main' into zix-http1
prothegee Jul 20, 2026
15a7403
extend zig dir for internal usage
prothegee Jul 20, 2026
5a69b30
bump to 0.5.x-rc2
prothegee Jul 21, 2026
3013c03
template for Dockerfile
prothegee Jul 21, 2026
70e6da0
re-defined meta info
prothegee Jul 21, 2026
a43ce56
use seperate handlers
prothegee Jul 21, 2026
baee980
add shared source
prothegee Jul 21, 2026
9d5b1ff
remove stale src file
prothegee Jul 21, 2026
1709d74
re-align minimal approach in main
prothegee Jul 21, 2026
71da3ef
re-adjusting entry 0.5.x-rc2 entry for zix
prothegee Jul 21, 2026
f874a56
Merge remote-tracking branch 'origin/main' into zix-http1
prothegee Jul 21, 2026
4945a65
Benchmark results: zix
github-actions[bot] Jul 21, 2026
af9c11b
use 16 shards
prothegee Jul 22, 2026
2612feb
Merge remote-tracking branch 'refs/remotes/fork/zix-http1' into zix-h…
prothegee Jul 22, 2026
a20ac7a
re-arange and remove local test
prothegee Jul 22, 2026
936c488
upload returns counted received body bytes
prothegee Jul 23, 2026
bee61fb
serialize and compress json per request
prothegee Jul 23, 2026
927b0be
item cache only, absolute 200 ms ttl
prothegee Jul 23, 2026
e7da520
list requests always query the database
prothegee Jul 23, 2026
e8c46ff
move db endpoints to engine-worker lanes
prothegee Jul 23, 2026
711566d
update lane wording, drop dead comments
prothegee Jul 23, 2026
0e5fb08
clean dead comments, collapse signatures
prothegee Jul 23, 2026
6d8071f
collapse handler signatures and sends
prothegee Jul 23, 2026
771dd5e
simplify static index comments
prothegee Jul 23, 2026
8609f17
remove unused internalServerError
prothegee Jul 23, 2026
bdd4244
remove unused Dataset deinit
prothegee Jul 23, 2026
b8028a9
wire db lanes, drop cache and mirror setup
prothegee Jul 23, 2026
0b6185a
remove response cache module
prothegee Jul 23, 2026
7d9f111
remove redis write-behind mirror
prothegee Jul 23, 2026
7bb02d8
describe the lane design in meta
prothegee Jul 23, 2026
6f1b32c
Merge remote-tracking branch 'origin/main' into zix-http1
prothegee Jul 23, 2026
0160520
Benchmark results: zix
github-actions[bot] Jul 24, 2026
7eb5b59
Merge main and port the saved results to the per-framework layout
MDA2AV Jul 24, 2026
ae34554
Merge remote-tracking branch 'origin/main' into zix-http1
prothegee Jul 25, 2026
f087ee9
Benchmark results: zix
github-actions[bot] Jul 26, 2026
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
5 changes: 5 additions & 0 deletions frameworks/zix/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.zig-cache
zig-out
zig-package
vendor
/zig*
78 changes: 40 additions & 38 deletions frameworks/zix/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,66 +4,68 @@ FROM alpine:3.20 AS build
ARG RETRY=6
ARG TARGETARCH
ARG RETRY_DELAY=3
ARG TIMEOUT_SEC=180
ARG ZIG_VERSION=0.16.0
ARG ZIX_VERSION=0.4.x-rc3
RUN apk add --no-cache ca-certificates curl git tar xz
ARG ZIX_VERSION=0.5.x-rc2
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 ;; \
arm64) ZIG_ARCH=aarch64 ;; \
*) echo "unsupported arch: ${TARGETARCH}" >&2; exit 1 ;; \
esac; \
curl -fsSL "https://ziglang.org/download/${ZIG_VERSION}/zig-${ZIG_ARCH}-linux-${ZIG_VERSION}.tar.xz" \
curl -fSL -m ${TIMEOUT_SEC} "https://ziglang.org/download/${ZIG_VERSION}/zig-${ZIG_ARCH}-linux-${ZIG_VERSION}.tar.xz" \
| tar -xJ -C /opt; \
mv "/opt/zig-${ZIG_ARCH}-linux-${ZIG_VERSION}" /opt/zig
ENV PATH="/opt/zig:${PATH}"

# 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 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
# curl can fall through to the codeberg tarball, and git clone talks to github.com
# and codeberg.org directly as the deeper fallback. RETRY and RETRY_DELAY bound
# every attempt.
COPY build.zig ./
COPY build.zig.zon.template ./build.zig.zon
COPY src ./src

# Resolve zix with zig fetch git+https
RUN set -eu; \
fetch() { \
rm -rf /src/vendor/zix; mkdir -p /src/vendor/zix; \
curl -fsSL --retry ${RETRY} --retry-delay ${RETRY_DELAY} --retry-all-errors "$1" -o /tmp/zix.tar.gz \
&& tar -xz --strip-components=1 -C /src/vendor/zix -f /tmp/zix.tar.gz; \
}; \
clone() { \
attempt=0; \
while [ "${attempt}" -lt "${RETRY}" ]; do \
rm -rf /src/vendor/zix; \
git clone --depth 1 --branch "${ZIX_VERSION}" "$1" /src/vendor/zix && return 0; \
fetch_zix() { \
url="$1"; attempt=1; \
while [ "${attempt}" -le "${RETRY}" ]; do \
if $(zig fetch --save ${url}); then \
return 0; \
fi; \
echo "zix: ${url} attempt ${attempt}/${RETRY} failed" >&2; \
attempt=$((attempt + 1)); \
sleep "${RETRY_DELAY}"; \
[ "${attempt}" -le "${RETRY}" ] && sleep "${RETRY_DELAY}"; \
done; \
return 1; \
}; \
fetch "https://github.com/prothegee/zix/archive/refs/heads/${ZIX_VERSION}.tar.gz" \
|| { echo "FAILED: curl ${RETRY} times from github" >&2; \
fetch "https://codeberg.org/prothegee/zix/archive/${ZIX_VERSION}.tar.gz" \
|| { echo "FAILED: curl ${RETRY} times from codeberg" >&2; \
clone "https://github.com/prothegee/zix.git" \
|| { echo "FAILED: git clone ${RETRY} times from github" >&2; \
clone "https://codeberg.org/prothegee/zix.git" \
|| { echo "FAILED: git clone ${RETRY} times from codeberg" >&2; exit 1; }; }; }; }
fetch_zix "git+https://codeberg.org/prothegee/zix#${ZIX_VERSION}" \
|| { echo "zix: codeberg exhausted ${RETRY} attempts" >&2; \
fetch_zix "git+https://github.com/prothegee/zix#${ZIX_VERSION}"; } \
|| { echo "zix: github exhausted ${RETRY} attempts" >&2; exit 1; }

WORKDIR /src
COPY build.zig build.zig.zon ./
COPY src ./src
# +aes+pclmul: x86_64_v3 omits AES-NI / PCLMUL,
# so zix TLS would compile the ~40x slower software AES-GCM.
# +adx speeds the RSA / Montgomery path. Every x86_64_v3 CPU has them, so it is safe.
RUN set -eu; \
case "${TARGETARCH:-amd64}" in \
amd64) ZIG_TARGET=x86_64-linux-musl; ZIG_CPU=x86_64_v3 ;; \
arm64) ZIG_TARGET=aarch64-linux-musl; ZIG_CPU=baseline ;; \
esac; \
zig build -Dtarget="${ZIG_TARGET}" -Dcpu="${ZIG_CPU}" --release=fast
zig build \
-Dtarget="${ZIG_TARGET}" \
-Dcpu="${ZIG_CPU}+aes+pclmul+adx" \
--release=fast --summary line;

# Self-signed Ed25519 cert generated at image build, baked at /etc/zix-tls.
RUN set -eu; \
mkdir -p /etc/zix-tls; \
openssl genpkey -algorithm ED25519 -out /etc/zix-tls/server.key; \
openssl req -new -x509 -key /etc/zix-tls/server.key -out /etc/zix-tls/server.cert \
-days 3650 -subj "/CN=localhost"

FROM alpine:3.20
COPY --from=build /src/zig-out/bin/zix /zix
EXPOSE 8080
ENTRYPOINT ["/zix"]
COPY --from=build /server/zig-out/bin/zix-http1 /zix-http1
COPY --from=build /etc/zix-tls /etc/zix-tls
EXPOSE 8080 8081
ENTRYPOINT ["/zix-http1"]
2 changes: 1 addition & 1 deletion frameworks/zix/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub fn build(b: *std.Build) void {
const zix_mod = zix_dep.module("zix");

const exe = b.addExecutable(.{
.name = "zix",
.name = "zix-http1",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
Expand Down
12 changes: 12 additions & 0 deletions frameworks/zix/build.zig.zon.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.{
.name = .zix_arena,
.version = "0.1.0",
.fingerprint = 0x84cceaddc218682f,
.minimum_zig_version = "0.16.0",
.paths = .{
"build.zig",
"build.zig.zon",
"src",
},
.dependencies = .{},
}
14 changes: 10 additions & 4 deletions frameworks/zix/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@
"display_name": "zix",
"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 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.",
"engine": "zix.Http1 URING Dispatch Model",
"description": "Zig HTTP/1.1 server on the zix.Http1 raw engine, .URING dispatch: per-worker SO_REUSEPORT io_uring loops, comptime Router, staged send sink. Dual listener: cleartext 8080, TLS 1.3 on 8081. DB endpoints run on engine-worker lanes: each worker pumps its own pipelined postgrez connections on its ring, named prepared statements, cache-aside single-item crud reads (200 ms TTL).",
"repo": "https://github.com/prothegee/zix",
"enabled": true,
"tests": [
"baseline",
"pipelined",
"limited-conn",
"json",
"upload",
"static"
"static",
"json",
"json-comp",
"json-tls",
"api-4",
"api-16",
"async-db",
"crud"
],
"maintainers": ["prothegee"]
}
35 changes: 35 additions & 0 deletions frameworks/zix/src/handlers/asyncdb.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//! GET /async-db?min=..&max=..&limit=.. : price-range item scan. Queues a
//! Job on the worker's postgres lane (dbpg.zig), answered async.

const std = @import("std");
const zix = @import("zix");

const dbpg = @import("../shared/dbpg.zig");
const response = @import("../shared/response.zig");

// --------------------------------------------------------- //

pub const PATH = "/async-db";

const ASYNC_DB_LIMIT_MAX: i64 = 50;

// --------------------------------------------------------- //

pub fn RESPONSE(req: *zix.Http1.Request, _: *zix.Http1.Response, _: *zix.Http1.Context) !void {
const head = req.head;
const fd = req.fd;

const min: i64 = if (zix.Http1.queryParam(head, "min")) |raw| std.fmt.parseInt(i64, raw, 10) catch 0 else 0;
const max: i64 = if (zix.Http1.queryParam(head, "max")) |raw| std.fmt.parseInt(i64, raw, 10) catch 0 else 0;
var limit: i64 = if (zix.Http1.queryParam(head, "limit")) |raw| std.fmt.parseInt(i64, raw, 10) catch 10 else 10;
if (limit < 1) limit = 1;
if (limit > ASYNC_DB_LIMIT_MAX) limit = ASYNC_DB_LIMIT_MAX;

const queued = dbpg.submitJob(head, .{ .ASYNC_DB = .{
.fd = fd,
.min = min,
.max = max,
.limit = limit,
} });
if (!queued) response.serviceUnavailable(fd);
}
61 changes: 61 additions & 0 deletions frameworks/zix/src/handlers/baseline.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//! GET/POST /baseline11?a=..&b=.. : sum the query values, plus the POST body
//! as an integer. Returns the sum as text/plain.

const std = @import("std");
const zix = @import("zix");

// --------------------------------------------------------- //

pub const PATH = "/baseline11";

// --------------------------------------------------------- //

fn sumQuery(query: []const u8) i64 {
var sum: i64 = 0;
var it = std.mem.tokenizeScalar(u8, query, '&');
while (it.next()) |pair| {
if (std.mem.indexOfScalar(u8, pair, '=')) |eq| {
sum += std.fmt.parseInt(i64, pair[eq + 1 ..], 10) catch 0;
}
}
return sum;
}

fn parseIntLoose(s: []const u8) i64 {
var i: usize = 0;
while (i < s.len and (s[i] == ' ' or s[i] == '\t' or s[i] == '\r' or s[i] == '\n')) i += 1;

var neg = false;
if (i < s.len and s[i] == '-') {
neg = true;
i += 1;
}

var n: i64 = 0;
while (i < s.len and s[i] >= '0' and s[i] <= '9') : (i += 1) {
n = n * 10 + (s[i] - '0');
}

return if (neg) -n else n;
}

// --------------------------------------------------------- //

pub fn RESPONSE(req: *zix.Http1.Request, _: *zix.Http1.Response, _: *zix.Http1.Context) !void {
const head = req.head;
const body = try req.body();
const fd = req.fd;

var sum: i64 = sumQuery(head.query);

if (req.method() == .POST and body.len > 0) {
sum += parseIntLoose(body);
}

var body_buf: [32]u8 = undefined;
const out = std.fmt.bufPrint(&body_buf, "{d}", .{sum}) catch return;

zix.Http1.sendSimpleFD(fd, 200, "text/plain", out) catch {
try zix.Http1.sendSimpleFD(fd, @intFromEnum(zix.Http1.Status.Code.INTERNAL_SERVER_ERROR), zix.Http1.Content.Type.TEXT_PLAIN.asString(), zix.Http1.Status.Code.INTERNAL_SERVER_ERROR.asString());
};
}
Loading