Performance
secnetperf-style micro-benchmarks over loopback UDP. Throughput figures use a
real TLS 1.3 handshake (quic-go BenchmarkTransfer model); the installed-keys
bypass is reserved for point latency micro-benchmarks only. Loopback throughput
swings ±20% run-to-run — trends and orders of magnitude matter more than
absolutes.
Two calibers
Section titled “Two calibers”| Caliber | Single-stream | Handshake | What it tells you |
|---|---|---|---|
Installed-keys, threaded std.Io |
~1.94 GB/s | bypassed | raw transport ceiling (README headline); skips transport-parameter negotiation |
| Real TLS 1.3 handshake | ~310–440 MB/s | real | the number real clients see; the headline on this page |
The installed-keys path bypasses the handshake (and thus RFC 9000 §7.4 transport-parameter negotiation), so treat ~1.94 GB/s as a ceiling, not a client-facing figure.
UDP loopback, real handshake
Section titled “UDP loopback, real handshake”| Metric | Value | Notes |
|---|---|---|
| Single-stream throughput | ~310–440 MB/s | 3 runs: 313 / 318 / 440 (±20% run-to-run) |
| Handshake time | ~0.6–1.0 ms/iter | TLS 1.3, transport parameters negotiated (RFC 9000 §7.4) |
| Transfer | 64 MB/iter | 8900 B datagram, CUBIC, 100 μs receiveTimeout |
| Percentile | Latency |
|---|---|
| P50 | 21.7 μs |
| P99 | 77.3 μs |
| P99.9 | 175.9 μs |
5000 iterations, 1 KB full QUIC round-trip after a real handshake.
| Multi-stream (4 concurrent) | Value | Notes |
|---|---|---|
| Aggregate | ~304 MB/s | stddev 4.5% — more stable than single-stream |
| Loss rate | Throughput | Notes |
|---|---|---|
| 1% (loopback) | 452 MB/s | CUBIC fast recovery |
| 5% (loopback) | 303 MB/s | |
| 1% (100 μs RTT) | 126 MB/s | |
| 5% (100 μs RTT) | 120 MB/s |
In-memory, single-thread
Section titled “In-memory, single-thread”No UDP overhead — isolates the connection/CRYPTO state machine.
| Metric | Value | Notes |
|---|---|---|
| Stream upload (16 MB) | 0.35 GB/s | CUBIC, cwnd = 272 KB |
| Echo P50 | 7.5 μs | 1 KB full QUIC round-trip (in-memory) |
| Echo P99 | 47.7 μs | tail varies with OS scheduling |
| Echo P99.9 | 665.2 μs | |
| 4-stream aggregate (4×4 MB) | 0.34 GB/s | shared cwnd |
CPU utilization (real-handshake suite)
Section titled “CPU utilization (real-handshake suite)”| Metric | Value |
|---|---|
| Real time | 3.90 s |
| User CPU | 3.21 s (~82% of one core) |
| Sys CPU | 4.25 s (~109%, multi-core accumulated) |
| Peak RSS | ~2.4 GB (bench arena accumulated, not production per-connection) |
High sys CPU comes from per-packet UDP sendto/recvfrom syscalls; throughput is
ACK-clock and shared-I/O-path limited, not pure CPU compute.
Other implementations
Section titled “Other implementations”Cross-implementation throughput figures are quoted from external benchmarks (secnetperf, KIT 2025, TQUIC, quic-go#3670) — not measured by quicz. The full source-attributed table lives on the feature comparison page.
Cross-platform
Section titled “Cross-platform”The nanoTime() helper has a Linux clock_gettime branch and all bench
artifacts build on Linux, so the suite also runs in a native aarch64 Linux
container. Loopback there goes through the Docker virtual NIC, so the numbers
are environment-bound ceilings, not quicz limits:
| Metric | macOS (native) | aarch64 Linux container |
|---|---|---|
| Single-stream (real handshake) | ~426–507 MB/s | ~51 MB/s (docker veth UDP ~60 MB/s ceiling) |
| DATAGRAM | ~199 MB/s | ~64 MB/s |
| Echo latency P50 | 20.1 μs | 31.6 μs |
Real bare-metal Linux throughput needs a non-virtualized host. Two runtime
notes: drainOutgoing batches datagrams via sendMany (one sendmmsg syscall
per batch on Linux; macOS keeps per-datagram sends), and receive buffers are
pooled (a 16-entry pool instead of per-datagram allocation).
Methodology
Section titled “Methodology”- Protocol — QUIC v1; throughput runs do a real TLS 1.3 handshake per connection; installed 1-RTT keys only for latency micro-benchmarks.
- Socket — loopback UDP, 8900-byte datagrams (macOS UDP limit 9000 B).
- I/O layer —
std.Io.Threaded(cross-platform; Linux auto-enables sendmmsg batching). - Build —
zig build-exe -OReleaseFast. - Platform — Apple M-series, macOS, Zig 0.16.
- Congestion — CUBIC (RFC 8312/9438); token-bucket pacer with ns precision.
- Variance — ±20% run-to-run (system load, CUBIC window dynamics, thermal); ranges given where multiple runs were taken.
Run it
Section titled “Run it”# Standardized suite: builds every benchmark (ReleaseFast), runs all in fixed# order, records platform/commit metadata + full output under# bench_results/<UTC timestamp>_<commit>.log (committed results are the baseline)scripts/run_bench_suite.shzig build bench-suite # same order, no result recording
# Individual benchmarkszig build run-quic-bench # installed-keys micro-benchmarkzig build run-quic-bench-hs # real-handshake throughput + latencyzig build run-quic-bench-simple # single-threaded raw processingzig build run-quic-bench-datagram # RFC 9221 DATAGRAM throughputzig build run-quic-bench-profile # per-phase profilingzig build run-congestion-bench # NewReno vs CUBIC simulated lossReading these numbers
Section titled “Reading these numbers”- Real handshake, not bypass. Throughput uses a fresh TLS 1.3 handshake per iteration, so transport parameters are negotiated (RFC 9000 §7.4) — the installed-keys path skips that and is only for latency points.
- ±20% variance. Loopback CUBIC at ~1 μs RTT makes single-stream runs noisy; multi-stream aggregate is steadier. Treat figures as orders of magnitude.
- No GSO / XDP on macOS. The main per-packet cost is QUIC processing CPU
(AES-128-GCM hw-accelerated ~4.9 μs/packet + framing); UDP
sendto~3.5–4.7 μs/packet is not dominant. Linux GSO/GRO (3–10×) or XDP would lift quicz. - Go / Rust benefit from zero-copy
sendmsg+ GSO on Linux, which this run does not exercise.
Benchmarks
Section titled “Benchmarks”- Echo latency (P50 / P99 / P99.9)
- Multi-stream concurrency (4 streams)
- Loss recovery (1% / 5%, loopback + 100 μs RTT)
- CPU utilization
- DATAGRAM throughput (RFC 9221)
- External interop throughput (quic-go / quiche / s2n-quic peers)
References
Section titled “References”- TQUIC Benchmark — Tencent’s multi-condition QUIC benchmark
- QUIC Interop Runner — interop + throughput via pcap
- KIT Performance Landscape (2025) — academic multi-implementation comparison
- secnetperf — Microsoft’s QUIC perf tool