Benchmarks

2026-10-06 — Zero-copy static files (sendfile, ADR-0027)

Same harness, host and caveats as the other reports (Docker Desktop / WSL2, Ryzen 7 7800X3D, server on CPUs 0-3, oha on 6-11, 64 connections, 10 s, ±15–20 % run-to-run).

Same run, all three servers

server  scenario        rps   p50_ms  p95_ms  p99_ms  peak_rss_mib
scb     static-1m     18597     3.32    5.97    7.57    18
scb     static-small  62374     0.96    1.84    2.45    19
nginx   static-1m     23477     2.47    4.59    7.00    61
nginx   static-small 102276     0.58    1.20    2.48    61
caddy   static-1m     13168     3.24   14.84   22.73    46
caddy   static-small  36022     1.16    5.56    9.93    47

1 MiB files: 10.4k → 18.6k req/s (0.42× → 0.79× nginx; 1.41× Caddy).

Variants measured (scb vs nginx in the same run)

variant                         scb rps   nginx rps
MSG_MORE head + fadvise          17513     24261
MSG_MORE head, no fadvise        19547     24213     (adopted without MSG_MORE)

posix_fadvise(WILLNEED) per response cost ≈11 % and was dropped; MSG_MORE on the response head showed no gain and was dropped.

Profile after (scripts/profile.sh —docker static-1m)

19.1k req/s, 3.55 CPUs. 70 % of scb’s CPU time is inside sendfile(2) itself, 10 % in writev of response heads, ~2 % openat2; scb’s own code is no longer visible. The remaining gap to nginx is kernel-side and needs a side-by-side profile of nginx.

Correctness

tests/integration/tests/sendfile.rs compares bytes for keep-alive sequences, ranges across the 1 MiB placeholder boundary, pipelining, HEAD, HTTP/1.0, h2c, TLS and cached applications. A sabotage run (sendfile path forced to fail) fails the plain-HTTP/1 tests and passes the cached one, proving which path each test takes.