Internals: benchmark reports
Release-mode comparison on the VM (run 7): 2026-10-12
The run-7 binaries on the development VM of the 2026-10-06 runs, with the same method, so the release-mode numbers of both hosts can be read side by side.
Host: VMware VM, AMD EPYC 7642, 8 vCPU, 31 GiB, Ubuntu 24.04, kernel 6.8. Server on CPUs
0-1 (two workers or event loops), applications on 2-3, oha on 4-7; 64 connections; one
NOFILE limit of 65535 for every process; kTLS and the open-file cache off on both
servers. The VM also served its usual low-traffic websites during the run (other
CPUs, no pinning); every server saw the same conditions, runs rotated the server order.
MODE=release: 10 s warm-up, 30 s measurement, 5 runs, medians.
scalws: the PGO + BOLT build of run 7 (ADR-0047, commit a7dc639); final with both
experimental settings, final-hyper with defaults. Versions: nginx 1.24.0 (Ubuntu 24.04
package) and 1.31.6 (built from the signed source tarball on this host); PHP-FPM 8.3,
Node 18, uvicorn 0.37 with two workers.
Every measurement of every server answered 2xx only. No run was excluded.
| scenario | scalws final | final-hyper | nginx 1.24 | nginx 1.31 | final / nginx 1.31 | final / nginx 1.24 |
|---|---|---|---|---|---|---|
| static-small | 70 555 | 68 717 | 68 170 | 68 253 | 1.03 | 1.03 |
| static-1m | 8 136 | 8 290 | 8 381 | 8 561 | 0.95 | 0.97 |
| respond | 109 391 | 104 219 | 110 143 | 116 992 | 0.94 | 0.99 |
| proxy | 57 009 | 52 457 | 51 668 | 53 683 | 1.06 | 1.10 |
| cache-hit | 99 289 | 91 384 | 62 576 | 63 091 | 1.57 | 1.59 |
| tls-h2-static-small | 63 497 | 63 034 | 57 312 | 61 233 | 1.04 | 1.11 |
| tls-static-1m | 1 808 | 1 745 | 1 218 | 1 206 | 1.50 | 1.48 |
| php | 29 276 | 27 530 | 24 810 | 25 178 | 1.16 | 1.18 |
| node | 27 879 | 26 464 | 27 768 | 28 435 | 0.98 | 1.00 |
| python | 11 947 | 12 174 | 11 993 | 11 802 | 1.01 | 1.00 |
p99 latency of every server (ms, median of 5 runs, p99_ms):
| scenario | scalws final | final-hyper | nginx 1.24 | nginx 1.31 |
|---|---|---|---|---|
| static-small | 1.61 | 1.80 | 1.65 | 1.60 |
| static-1m | 13.50 | 13.85 | 13.43 | 13.21 |
| respond | 1.03 | 1.07 | 1.01 | 0.95 |
| proxy | 2.08 | 2.55 | 2.18 | 1.98 |
| cache-hit | 1.09 | 1.20 | 1.74 | 1.76 |
| tls-h2-static-small | 1.94 | 2.16 | 1.88 | 1.79 |
| tls-static-1m | 81.38 | 72.38 | 87.48 | 79.76 |
| php | 3.42 | 4.04 | 4.64 | 4.26 |
| node | 4.72 | 5.22 | 4.76 | 5.05 |
| python | 12.38 | 10.27 | 10.39 | 10.83 |
Server CPU per request of every server (µs, median of 5 runs, cpu_us_per_req):
| scenario | scalws final | final-hyper | nginx 1.24 | nginx 1.31 |
|---|---|---|---|---|
| static-small | 28.30 | 29.05 | 29.21 | 29.27 |
| static-1m | 245.38 | 240.92 | 238.29 | 233.04 |
| respond | 18.25 | 19.15 | 18.12 | 17.06 |
| proxy | 35.03 | 37.96 | 38.58 | 37.19 |
| cache-hit | 20.11 | 21.84 | 31.93 | 31.67 |
| tls-h2-static-small | 31.40 | 31.61 | 34.77 | 32.54 |
| tls-static-1m | 1103.38 | 1143.08 | 1638.85 | 1654.31 |
| php | 49.51 | 57.70 | 72.49 | 71.42 |
| node | 44.09 | 48.25 | 47.96 | 45.58 |
| python | 74.70 | 81.92 | 79.77 | 74.70 |
Peak resident memory of the server processes (MiB, median of 5 runs, peak_rss_mib):
| scenario | scalws final | final-hyper | nginx 1.24 | nginx 1.31 |
|---|---|---|---|---|
| static-small | 32 | 35 | 46 | 47 |
| static-1m | 34 | 35 | 46 | 47 |
| respond | 32 | 35 | 46 | 47 |
| proxy | 34 | 41 | 48 | 49 |
| cache-hit | 33 | 35 | 47 | 47 |
| tls-h2-static-small | 39 | 39 | 54 | 55 |
| tls-static-1m | 40 | 47 | 54 | 55 |
| php | 34 | 37 | 47 | 48 |
| node | 34 | 36 | 48 | 48 |
| python | 35 | 37 | 48 | 49 |
Run-to-run spread (coefficient of variation of requests/s, %), scalws final / nginx 1.31: static-small 3.6 / 1.6; static-1m 1.8 / 2.6; respond 1.6 / 3.8; proxy 4.2 / 7.2; cache-hit 5.0 / 4.0; tls-h2-static-small 4.0 / 2.5; tls-static-1m 10.2 / 1.5; php 9.1 / 5.8; node 4.7 / 7.4; python 3.7 / 2.2.
Reading it
- ScalWS is ahead of nginx 1.31 on the small static file (1.03×), the reverse proxy (1.06×), cache hits (1.57×), TLS + HTTP/2 (1.04×), HTTPS 1 MiB (1.50×) and PHP (1.16×); level on Python (1.01×) and Node.js (0.98×, inside the spread of both); behind on the fixed response (0.94×) and the 1 MiB file over plain HTTP (0.95×).
- The fixed-response gap is the one bare metal shows as well (0.97× there); on two VM CPUs nginx 1.31’s lead is larger.
- The VM’s run-to-run spread is wider than bare metal’s (coefficient of variation up to 10 % for the HTTPS 1 MiB scenario): read ratios within about 5 % as level.
- Compared with the 2026-10-06 baseline on the same VM (scalws 1.0.0-rc.1 before the Adaptive Runtime, against nginx 1.24): fixed response 0.85× → 0.99×, reverse proxy 0.93× → 1.10×, Node.js 0.79× → 1.00× against nginx 1.24.
Results: results/vm-r7 on the VM (aggregate.csv, aggregate.txt,
run-1 … run-5).