Skip to content

Commit 3ddfa65

Browse files
committed
docs(dataplane): real full-sweep results; mark io_uring engine as WIP
poll beats nginx 1.16x on 16 KB and ~2.3x on 1 MB (median of 3, 4 core) — the win grows with body size, exactly as the splice thesis predicts. io_uring engine accepts but doesn't move bytes yet (0 req/s); marked opt-in/WIP pending local strace, poll is the validated default.
1 parent 40bd11b commit 3ddfa65

1 file changed

Lines changed: 21 additions & 15 deletions

File tree

packages/dataplane/README.md

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,35 @@ zig build -Doptimize=ReleaseFast && bash bench/run.sh
6767
## Roadmap
6868

6969
1. **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.
7174
3. **kTLS** — terminate TLS in-kernel so encrypted bodies can *still* splice; the
7275
key to beating nginx on HTTPS body throughput.
7376
4. HTTP/1.1 parse for host routing + `X-Forwarded-*`; HTTP/2; WebSocket.
7477
5. Control-plane hand-off: consume certs/config from disk + reload on `SIGHUP`
7578
(the pattern rpx's cluster mode already uses).
7679
6. 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 ~*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 ~*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

Comments
 (0)