This benchmark compares standalone websocket echo servers on the same local machine:
zwssynczwssync + deadlinezwsasynczwsasync + deadlineuWebSocketssyncuWebSocketssync + deadlineuWebSocketsasyncuWebSocketsasync + deadline
The client in benchmark/bench.zig is shared across every peer:
- opens N TCP connections
- performs one websocket upgrade per connection
- sends prebuilt masked websocket frames in batches of configurable in-flight depth
- flushes once per batch and then discards the echoed frames by fixed byte count
This keeps the client overhead small and lets the benchmark cover both:
- ping-pong mode with
PIPELINE=1 - pipelined mode with
PIPELINE>1
That makes the comparison more useful for implementations such as uWebSockets that can benefit from higher in-flight depth while keeping the client implementation identical for every server under test.
zig build bench-compare -Doptimize=ReleaseFastEnvironment overrides:
LOW_CONNS=1 HIGH_CONNS=250000 ITERS=200000 WARMUP=10000 MSG_SIZE=16 zig build bench-compare -Doptimize=ReleaseFast
LOW_CONNS=1 HIGH_CONNS=250000 MAX_TOTAL_MSGS=4000000 MAX_TOTAL_WARMUP_MSGS=200000 PIPELINE_DEPTH=8 MSG_SIZE=16 zig build bench-compare -Doptimize=ReleaseFast
BENCH_CPU_POLICY=all BENCH_SERVER_WORKERS=0 zig build bench-compare -Doptimize=ReleaseFast
ROUNDS=1 BENCH_TIMEOUT_MS=300000 ZWS_DEADLINE_MS=30000 UWS_DEADLINE_MS=30000 zig build bench-compare -Doptimize=ReleaseFastNotes:
uWebSocketsanduSocketsare cloned on demand under.zig-cache/.- The
uWebSocketsbenchmark build uses no TLS and no websocket compression. - The default workload is a small binary echo frame, which is a transport-focused benchmark rather than an application benchmark.
Source: benchmark/results/latest.json
Config: host=127.0.0.1 path=/ rounds=1 low_conns=1 mid_conns=1000 high_conns=250000 iters=200000 warmup=10000 max_total_msgs=4000000 max_total_warmup_msgs=200000 pipeline_depth=8 msg_size=16 bench_timeout_ms=600000 server_workers=1 adaptive_conns=1000 shard_conns=25000 cpu_policy=single zws_deadline_ms=30000 uws_deadline_ms=30000
| Suite | zws-sync | zws-sync+dl | zws-async | zws-async+dl | uWS-sync | uWS-sync+dl | uWS-async | uWS-async+dl | fastwebsockets |
|---|---|---|---|---|---|---|---|---|---|
| 1 conn throughput / non-pipelined | avg 156421.46 peak 156421.46 |
avg 160225.97 peak 160225.97 |
avg 161023.81 peak 161023.81 |
avg 160211.54 peak 160211.54 |
avg 158788.88 peak 158788.88 |
avg 148144.51 peak 148144.51 |
avg 130748.77 peak 130748.77 |
avg 134297.87 peak 134297.87 |
avg 140638.62 peak 140638.62 |
| 1 conn throughput / pipelined | avg 403710.90 peak 403710.90 |
avg 410551.60 peak 410551.60 |
avg 374282.68 peak 374282.68 |
avg 421768.97 peak 421768.97 |
avg 404486.68 peak 404486.68 |
avg 410517.33 peak 410517.33 |
avg 375780.80 peak 375780.80 |
avg 399272.00 peak 399272.00 |
avg 385069.05 peak 385069.05 |
| 1000 conn throughput / non-pipelined | avg 404213.09 peak 404213.09 |
avg 365511.21 peak 365511.21 |
avg 381941.26 peak 381941.26 |
avg 336414.92 peak 336414.92 |
avg 332890.35 peak 332890.35 |
avg 348612.99 peak 348612.99 |
avg 364424.51 peak 364424.51 |
avg 340034.45 peak 340034.45 |
avg 362738.09 peak 362738.09 |
| 1000 conn throughput / pipelined | avg 658280.04 peak 658280.04 |
avg 617150.38 peak 617150.38 |
avg 639534.53 peak 639534.53 |
avg 644703.10 peak 644703.10 |
avg 685058.89 peak 685058.89 |
avg 646138.40 peak 646138.40 |
avg 388465.12 peak 388465.12 |
avg 447635.45 peak 447635.45 |
avg 326240.83 peak 326240.83 |
| 250000 conn throughput / non-pipelined | avg 76806.09 peak 76806.09 |
avg 76044.99 peak 76044.99 |
avg 65748.61 peak 65748.61 |
avg 44606.64 peak 44606.64 |
avg 52641.37 peak 52641.37 |
avg 63984.27 peak 63984.27 |
avg 45718.78 peak 45718.78 |
avg 56300.01 peak 56300.01 |
avg 43521.25 peak 43521.25 |
| 250000 conn throughput / pipelined | avg 288978.59 peak 288978.59 |
avg 541034.51 peak 541034.51 |
avg 423575.62 peak 423575.62 |
avg 519667.45 peak 519667.45 |
avg 335235.64 peak 335235.64 |
avg 394137.44 peak 394137.44 |
avg 126070.49 peak 126070.49 |
avg 148470.26 peak 148470.26 |
avg 85577.64 peak 85577.64 |
Each cell shows average msg/s across rounds and peak single-round msg/s. Fairness notes: all peers use the same benchmark client, identical per-suite client settings, randomized per-connection service order, fresh server processes per round, and the configured server CPU policy.
bench-compare is the low-noise harness:
- builds
zwsbinaries once - builds
uWebSocketsbenchmark server once - runs six suites across three connection loads:
1 conn throughput / non-pipelined1 conn throughput / pipelined1000 conn throughput / non-pipelined1000 conn throughput / pipelined250000 conn throughput / non-pipelined250000 conn throughput / pipelined- runs strict interleaved rounds inside each suite across eight peers:
zws-synczws-sync+dlzws-asynczws-async+dluWS-syncuWS-sync+dluWS-asyncuWS-async+dl- prints per-suite average and peak msg/s, plus a final average/peak matrix table
- defaults to
1round per suite because the default high-connection workload uses 250k connections - randomizes the client-side service order in high-connection runs so every connection sends and receives over time instead of hammering a fixed prefix
- defaults to
BENCH_CPU_POLICY=single, which pins every server process to CPU 0 on Linux;BENCH_CPU_POLICY=alldisables pinning for all-core comparisons - switches zws high-connection server runs to the public adaptive frame-server path at
BENCH_ADAPTIVE_CONNSconnections, default1000 - shards high-connection clients across destination ports using
BENCH_SHARD_CONNS, default25000, to avoid the loopback ephemeral-port ceiling per destination - gives high-connection deadline peers at least
BENCH_TIMEOUT_MSof deadline budget so connection setup at 250k sockets does not invalidate the deadline comparison - writes
benchmark/results/latest.html, which contains browser-theme-aware average and peak throughput graphs scaled independently per chart
Environment overrides:
ROUNDS=1 LOW_CONNS=1 MID_CONNS=1000 HIGH_CONNS=250000 ITERS=200000 WARMUP=10000 PIPELINE_DEPTH=8 MSG_SIZE=16 zig build bench-compare -Doptimize=ReleaseFast
ROUNDS=1 LOW_CONNS=1 MID_CONNS=1000 HIGH_CONNS=250000 MAX_TOTAL_MSGS=4000000 MAX_TOTAL_WARMUP_MSGS=200000 PIPELINE_DEPTH=16 MSG_SIZE=16 zig build bench-compare -Doptimize=ReleaseFast
BENCH_CPU_POLICY=all BENCH_SERVER_WORKERS=0 zig build bench-compare -Doptimize=ReleaseFast
BENCH_TIMEOUT_MS=300000 ZWS_DEADLINE_MS=30000 UWS_DEADLINE_MS=30000 zig build bench-compare -Doptimize=ReleaseFast