Benchmarks
hcs is the HTTP layer of an araara application, so its throughput is araara's throughput. These are local, single-machine numbers from the HttpArena harness — hcs (OCaml/Eio) measured side by side with reference Go, Rust, and PHP servers under identical conditions. They are a snapshot, not the official leaderboard, and the caveats matter; read them before drawing conclusions.
These are reference numbers measured on a single local machine, so every server runs under identical conditions. They are not the official http-arena.com leaderboard figures — that harness pins the server and the load generators to separate core sets on 64-core hardware. Use these for apples-to-apples comparison on this box, not for ranking.
Read these as ceilings, not forecasts. Each profile drives one narrow path — a plaintext reply, a static file, a single query — under a synthetic load generator. A real application is a different shape: it mixes routing, your business logic, serialization, database round-trips, and I/O waits in proportions no micro-benchmark captures, so these figures will not predict its throughput. Treat them only as a rough sense of the maximum a given path can reach on this hardware. The number that actually matters is the one you measure on your own application, under your own load — so measure that.
Snapshot: 2026-06-14, hcs 0.14.2. Server and client both run on the in-house
httpsans-I/O codec (http = 0.5.3), with stock GC (no tuning) and streaming HTTP/1.1 request bodies. Every run returned 0 × 5xx.
The machine
| CPU | AMD Ryzen 9 9950X — 16 cores / 32 threads, boost ≤ 5.76 GHz |
| RAM | 60 GiB |
| OS | openSUSE Tumbleweed, kernel 7.0.11 |
| Eio backend | io-uring (EIO_BACKEND=io-uring), HCS_H2_MAX_STREAMS=64 |
| hcs domains | 16 (physical cores; not the 32 SMT threads) |
| hcs GC | stock — no tuning by default (opt in with HCS_GC_TUNE=on) |
The servers
| Server | Language | Source |
|---|---|---|
| hcs | OCaml 5.4 (Eio) | this stack, local build, v0.14.2 |
| go-fasthttp | Go | HttpArena reference image |
| hyper | Rust | HttpArena reference image |
| actix | Rust | HttpArena reference image |
| swoole | PHP | HttpArena reference image |
Throughput and memory
Throughput in requests/second, alongside peak container RSS. — means the
server does not serve that profile here (not a failure). Bold marks the best
throughput in each row.
| Profile | hcs (OCaml) | go-fasthttp (Go) | hyper (Rust) | actix (Rust) | swoole (PHP) |
|---|---|---|---|---|---|
| baseline | 2.52 M / 101 MiB | 2.61 M / 49 MiB | 3.30 M / 23 MiB | 3.16 M / 35 MiB | 3.03 M / 63 MiB |
| pipelined | 15.57 M / 103 MiB | 18.9 M / 46 MiB | 22.1 M / 23 MiB | 19.2 M / 37 MiB | 5.02 M / 63 MiB |
| limited-conn | 1.62 M / 109 MiB | 1.52 M / 101 MiB | 2.09 M / 63 MiB | 1.90 M / 59 MiB | 1.91 M / 133 MiB |
| json | 381 K / 160 MiB | 338 K / 142 MiB | — | 811 K / 74 MiB | 364 K / 143 MiB |
| json-comp | 161 K / 335 MiB | 34 K / 774 MiB | — | 13 K / 63 MiB | 557 K / 144 MiB |
| upload | 1 208 / 325 MiB | 1 284 / 31.3 GiB | — | 3 729 / 195 MiB | 398 / 1.1 GiB |
| async-db | 146 K / 137 MiB | 84 K / 147 MiB | — | 128 K / 62 MiB | 198 K / 143 MiB |
| api-4 | 67 K / 122 MiB | 138 K / 260 MiB | — | 185 K / 74 MiB | 69 K / 136 MiB |
| api-16 | 214 K / 180 MiB | 162 K / 244 MiB | — | 264 K / 131 MiB | 252 K / 219 MiB |
| static | 1.09 M / 104 MiB | 981 K / 71 MiB | — | — | 798 K / 85 MiB |
| baseline-h2 | 4.88 M / 130 MiB | — | 4.81 M / 226 MiB | 2.72 M / 268 MiB | 2.11 M / 108 MiB |
| static-h2 | 103 K / 619 MiB | — | 297 K / 590 MiB | — | 363 K / 366 MiB |
| echo-ws | 2.52 M / 88 MiB | 1.77 M / 76 MiB | — | — | — |
| fortunes | 70 K / 237 MiB | — | — | — | — |
| crud | 196 K / 375 MiB | — | — | — | — |
echo-ws compares against the separate go-websocket image; fortunes and
crud are hcs-only in this set. actix is excluded from static (its file
handler reads disk per request with no cache and thrashes here, so the column
is not comparable).
What stands out
- WebSocket echo is a strength. hcs leads
echo-wsat 2.52 M / 88 MiB vs go-websocket's 1.77 M / 76 MiB. - HTTP/2 baseline leads.
baseline-h2is 4.88 M req/s, just ahead of hyper and well ahead of actix and swoole. - Static files (HTTP/1.1) are #1 in class at 1.09 M req/s.
- Uploads are constant-memory. hcs serves 500 KB–20 MB bodies at 325 MiB, where go-fasthttp matches the rate but uses 31.3 GiB; actix leads the byte-bound rate at 3 729 req/s.
json-compbeats Go and Rust here (161 K vs 34 K / 13 K), though swoole's OpenSSL/brotli path is far ahead at 557 K.- DB/mixed is competitive, not dominant.
api-16beats go-fasthttp (214 K vs 162 K);api-4is the weak blended case at 67 K. static-h2is the soft spot. TLS bulk throughput trails hyper and swoole; memory is now bounded (619 MiB, down from a multi-GiB regression) after thehttp = 0.5.3HTTP/2 output-queue cap.
How it's measured
- Harness: HttpArena
benchmark-lite.sh(laptop driver — no CPU pinning). Load generators (gcannon / wrk / h2load) run in Docker on the same host, sharing the 32 threads with the server under test. - Because load generation and server share cores, absolute numbers are lower than the published leaderboard, and servers that spend more CPU client-side are penalized. Treat columns as comparable to each other on this machine, not to http-arena.com. Run-to-run variance is roughly ±5–10 %.
- "Mem" is peak container RSS during the best run. The hcs column is the v0.14.2 build; reference columns are retained from the unchanged reference-image sweep on this host.
- Out of scope (no OCaml libraries / not built here): HTTP/3, gRPC, and the gateway/production-stack mixes.
Reproduce
$ arena/build.sh$ arena/compare.sh upload hcs go-fasthttp hyper actix swoole$ arena/h2spec.sh