Skip to content

Latest commit

 

History

History
108 lines (84 loc) · 6.92 KB

File metadata and controls

108 lines (84 loc) · 6.92 KB

WebSocket Benchmarks

This benchmark compares standalone websocket echo servers on the same local machine:

  • zws sync
  • zws sync + deadline
  • zws async
  • zws async + deadline
  • uWebSockets sync
  • uWebSockets sync + deadline
  • uWebSockets async
  • uWebSockets async + 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.

Run

zig build bench-compare -Doptimize=ReleaseFast

Environment 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=ReleaseFast

Notes:

  • uWebSockets and uSockets are cloned on demand under .zig-cache/.
  • The uWebSockets benchmark 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.

Latest Comparison

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.

Harness

bench-compare is the low-noise harness:

  • builds zws binaries once
  • builds uWebSockets benchmark server once
  • runs six suites across three connection loads:
  • 1 conn throughput / non-pipelined
  • 1 conn throughput / pipelined
  • 1000 conn throughput / non-pipelined
  • 1000 conn throughput / pipelined
  • 250000 conn throughput / non-pipelined
  • 250000 conn throughput / pipelined
  • runs strict interleaved rounds inside each suite across eight peers:
  • zws-sync
  • zws-sync+dl
  • zws-async
  • zws-async+dl
  • uWS-sync
  • uWS-sync+dl
  • uWS-async
  • uWS-async+dl
  • prints per-suite average and peak msg/s, plus a final average/peak matrix table
  • defaults to 1 round 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=all disables pinning for all-core comparisons
  • switches zws high-connection server runs to the public adaptive frame-server path at BENCH_ADAPTIVE_CONNS connections, default 1000
  • shards high-connection clients across destination ports using BENCH_SHARD_CONNS, default 25000, to avoid the loopback ephemeral-port ceiling per destination
  • gives high-connection deadline peers at least BENCH_TIMEOUT_MS of 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