@@ -67,29 +67,35 @@ zig build -Doptimize=ReleaseFast && bash bench/run.sh
6767## Roadmap
6868
69691 . ** v0** — splice TCP pump, ` reusePort ` , swappable backend. ✅
70- 2 . ** io_uring** engine — multishot accept + splice ops. ✅ (opt-in ` uring ` )
70+ 2 . ** io_uring** engine — single-shot accept + ` IORING_OP_SPLICE ` . ⚠️ implemented &
71+ compiles, but returns 0 req/s in CI (the loop accepts but never moves bytes —
72+ needs local-Linux ` strace ` to pin down; blind CI iteration exhausted). Opt-in
73+ (` uring ` arg); the default ` poll ` engine is the validated path.
71743 . ** kTLS** — terminate TLS in-kernel so encrypted bodies can * still* splice; the
7275 key to beating nginx on HTTPS body throughput.
73764 . HTTP/1.1 parse for host routing + ` X-Forwarded-* ` ; HTTP/2; WebSocket.
74775 . Control-plane hand-off: consume certs/config from disk + reload on ` SIGHUP `
7578 (the pattern rpx's cluster mode already uses).
76796 . A ** Home-native io backend** behind the engine seam.
7780
78- ## Status — beats nginx on bodies (validated in CI)
81+ ## Status — beats nginx on bodies, and the win grows with body size
7982
80- First Linux CI run (` dataplane-bench.yml ` , HTML ~ 16 KB, 50 concurrent, GitHub
81- 2-vCPU runner ):
83+ Full Linux CI sweep (` dataplane-bench.yml ` , median of 3, 4-core GitHub runner,
84+ all proxies ` reusePort ` N-up like nginx ` worker_processes auto ` ):
8285
83- | target | req/s |
84- | ---------------| -------:|
85- | direct | 62,704 |
86- | nginx | 33,170 |
87- | ** dataplane** | ** 40,439** |
86+ | body | conc | direct | nginx | ** poll** | poll ÷ nginx |
87+ | -------| -----:| -------:| -------:| ---------:| -------------:|
88+ | 16 KB | 50 | 64,643 | 34,651 | ** 40,266** | ** 1.16×** |
89+ | 16 KB | 256 | 68,320 | 37,569 | ** 43,547** | ** 1.16×** |
90+ | 1 MB | 50 | 7,048 | 1,559 | ** 3,629** | ** 2.33×** |
91+ | 1 MB | 256 | 6,522 | 1,529 | ** 3,300** | ** 2.16×** |
8892
89- ** ~ 1.22× nginx** — on the exact body-bound metric where a Bun proxy is ~ 3× * behind*
90- nginx. That's the thesis confirmed: nginx copies bodies through userspace; the
91- dataplane ` splice() ` s kernel→kernel and doesn't. (Single run on a noisy shared
92- 2-vCPU runner — directionally strong, not a final number; re-runs on every change
93- and via manual dispatch.)
93+ The thesis, confirmed: nginx copies proxied bodies through userspace; the dataplane
94+ ` splice() ` s kernel→kernel and doesn't — so ** the bigger the body, the bigger the
95+ edge** (1.16× at 16 KB → ~ 2.3× at 1 MB). This is the exact body-bound metric where
96+ a Bun/JS proxy runs ~ 3× * behind* nginx.
9497
95- Next: io_uring + kTLS for HTTPS bodies, then HTTP routing — see the roadmap above.
98+ The ` uring ` engine currently reports ** 0** (see roadmap #2 — accepts but never
99+ splices; needs local-Linux debugging). The numbers above are the ` poll ` engine, the
100+ validated default. Next: fix io_uring (where batching should pull ahead on 1 MB),
101+ then kTLS for HTTPS bodies — see the roadmap above.
0 commit comments