Internals: benchmark reports

Upstream pools and route matching: prefix-only regression check, 2026-10-14

Machine and pinning as in 2026-10-10-xeon-bare-metal-pgo.md: 2× Xeon E5-2650 v2 (Ivy Bridge EP, no AVX2), Ubuntu 26.04, kernel 7.0, performance governor, turbo off. Server on CPUs 0-3 (four physical cores of socket 0, 4 workers), upstream and applications on 4-7, oha 1.16.0 on all of socket 1 (8-15, 24-31), 64 connections.

Commits: base = d61a50f (before Kubernetes phase 2a), new = 2384720 (upstream pools, route matching and route policies). Both are plain release builds of the same profile (cargo build --release --locked -p scalwsd --features http3, thin LTO, one codegen unit, no PGO or BOLT, no target-specific CPU features); the shipped bench/configs/scalws.yaml enables an HTTP/3 listener, so both need the http3 feature. The numbers are therefore lower than those of the PGO + BOLT builds in run 7 and are only comparable with each other.

Configuration under test: bench/configs/scalws.yaml unchanged, which has prefix routes only (/api to a single-address proxy, /respond), so new takes the prefix fast path and the existing ProxyHandler. bench/multi.sh with VARIANTS="base=... new=...", MODE=release: 10 s warm-up, 30 s measurement, 5 runs, the order of the two variants rotating from run to run; medians. Every measurement answered 2xx only; no run was excluded.

Gate: new requests per second at least 0.98× base and server CPU per request at most 1.02× base, per scenario.

scenariobase req/snew req/snew / basecpu_us basecpu_us newcpu new / basegate
static-small75 64174 7870.98952.8753.471.011pass
respond125 460127 6741.01831.8731.320.983pass
proxy51 60151 0550.98977.5078.331.011pass
cache-hit93 19594 4901.01442.9042.320.986pass

Spread of the five runs (req/s, min to max, CV): static-small base 75 170-77 079 (0.9 %), new 73 403-76 166 (1.6 %); respond base 124 536-128 275 (1.2 %), new 122 535-128 870 (2.5 %); proxy base 51 422-51 842 (0.3 %), new 50 227-51 442 (1.1 %); cache-hit base 92 142-94 571 (1.0 %), new 91 842-96 017 (2.0 %). The differences of static-small and proxy (about 1 %) are inside the spread of the runs, and respond and cache-hit moved the other way by a similar amount.

p99 latency (ms), base / new: static-small 1.07 / 1.07; respond 0.67 / 0.65; proxy 2.04 / 2.23; cache-hit 0.92 / 0.89.

Peak resident memory of the server (MiB), base / new: static-small 44 / 43; respond 43 / 43; proxy 45 / 51; cache-hit 45 / 51. The value is the peak since the server started (the four scenarios run against one process in this order), so proxy and cache-hit include what the earlier scenarios left allocated. new peaked higher from the proxy scenario on in every run (proxy: 46-51 MiB against 44-45 MiB); the cause is not investigated here and it does not show up in CPU per request. The proxy p99 (+9 %) moved with the throughput spread of the runs; the median latency is unchanged.

Verdict

The gate holds on all four scenarios: no throughput drop above 2 % and no CPU per request increase above 2 %. The prefix-only configuration costs the same with upstream pools, route matching and route policies in the binary as before.

Results, in the bench host’s results directory: results/xeon-pools-ab (aggregate.csv, aggregate.txt, run-1 … run-5); binaries /opt/scalws-pools-base/scalwsd and /opt/scalws-pools-new/scalwsd.