End-to-end reproducer for the Linux io_uring runtime numbers shown in the
top-level Performance section. The suite cross-compiles
bench/http_server.zig for aarch64-linux-musl, packages it with
wrk 4.2.0 into an Alpine image, and runs the wrk suite from inside the
same OCI container against 127.0.0.1 so the wire is in-VM kernel loopback
(no virtio-net, no host bridge).
Tested with Apple container 0.11
on macOS 26.4 (kernel 6.18.5 inside the VM). Should also work with docker
or podman — set RUNTIME=docker and pick the right TARGET.
# from the repo root
./bench/linux/run.shTunables (env vars):
| var | default | meaning |
|---|---|---|
RUNTIME |
container |
OCI CLI to invoke (also docker) |
TARGET |
aarch64-linux-musl |
Zig cross-compile target |
IMAGE |
nano-bench:latest |
image tag |
NAME |
nano-bench |
container name |
CPUS |
8 |
vCPU allocation |
MEM |
4096M |
memory allocation |
WORKERS |
4 |
nanoapi worker count |
DURATION |
15s |
wrk -d duration |
bench/linux/
├── Containerfile nanoapi server image (alpine + wrk + binary)
├── run.sh build → run → bench → tear down
├── pipeline.lua 16-request pipelined wrk script
├── post-users.lua POST body matching bench/http_server.zig BodyModel
├── auth-headers.lua Authorization + Cookie session= for /auth
└── comparison/
├── fiber/ Go Fiber 2.52 server + Containerfile
└── actix/ actix-web 4.9 server + Containerfile
container build -t fiber-bench -f bench/linux/comparison/fiber/Containerfile bench/linux/comparison/fiber
container run -d --name fb --rm --cpus 8 -m 4096M \
--mount type=bind,source=$PWD/bench/linux,target=/scripts,readonly fiber-bench
container exec fb wrk -t4 -c64 -d15s --latency -s /scripts/pipeline.lua http://127.0.0.1:8080/
container stop fb
container build -t actix-bench -f bench/linux/comparison/actix/Containerfile bench/linux/comparison/actix
container run -d --name ab --rm --cpus 8 -m 4096M \
--mount type=bind,source=$PWD/bench/linux,target=/scripts,readonly actix-bench
container exec ab wrk -t4 -c64 -d15s --latency -s /scripts/pipeline.lua http://127.0.0.1:8080/
container stop abAll three servers expose the same three routes (GET /, POST /users,
GET /auth) with matching JSON shapes, so the wrk lua scripts work
unchanged across them.
- Apple
containerruns each container in a lightweight VM; numbers will differ on bare metal. The point of the suite is relative comparison with everything sharing the same VM topology. Prefork: truefor Fiber crashes under Apple container's rootfs (no re-exec of/proc/self/exe); the bench drops it and uses the default goroutine-per-connection model.- actix-web
lto = "thin", not"fat", to keep the build under five minutes. Fat-LTO would gain a few percent. bench/http_server.zig'sparseRuntimeonly knowsauto/event_loop/thread_per_connection.autois sufficient — on Linux it resolves toio_uringviaeffectiveRuntimeinsrc/server.zig.