Repository navigation
morojs: gateway-h3 on the nginx QUIC edge; loopback TLS listens; Node… - #1699
Conversation
|
/benchmark -f morojs --save |
|
👋 Benchmark request received. A collaborator will review and approve the run. |
|
ehi @M-Chris since the change is on the edges, maybe it is better to run only the touched profiles, one by one with -t (gateway-h3, gateway-64, production-stack). In my runs a full --save moved profiles we did not touch by several percent (gateway-64 +15%, production-stack -4%), so a full save mixes the real change with machine noise. The Node pin touches every profile, true, but in practice it should change only json-comp, so that one can go in a separate -t run. |
|
/benchmark -f morojs -t gateway-h3 --save |
|
👋 Benchmark request received. A collaborator will review and approve the run. |
|
/benchmark -f morojs -t json-comp --save |
|
👋 Benchmark request received. A collaborator will review and approve the run. |
|
/benchmark -f morojs -t gateway-64 --save |
|
👋 Benchmark request received. A collaborator will review and approve the run. |
|
/benchmark -f morojs -t production-stack --save |
|
👋 Benchmark request received. A collaborator will review and approve the run. |
|
/benchmark -f morojs -t echo-ws-pipeline --save |
|
👋 Benchmark request received. A collaborator will review and approve the run. |
|
/benchmark -f morojs -t echo-ws --save |
|
👋 Benchmark request received. A collaborator will review and approve the run. |
|
/benchmark -f morojs -t echo-ws-limited --save |
|
👋 Benchmark request received. A collaborator will review and approve the run. |
|
@MDA2AV a process note, since this PR shows the problem well. This change touches seven profiles (three edges, the Node pin, and an engine release Proposal: let -t take a comma-separated list, so one run and one approval cover /benchmark -f morojs -t gateway-h3,gateway-64,production-stack,json-comp --save Changes needed are small: the profile pattern in pr-commands.yml, the profile loop in |
|
👋 Benchmark request received. A collaborator will review and approve the run. |
|
Ok, can you add that change to the benchmark script? Ill merge the pr and you can rebase here |
A change that touches several profiles had two ways to be measured, both
wrong for it. One -t run per profile is one approval and one results commit
each, posted only after the previous run finishes, because a PR holds one
pending run; seven touched profiles is a day of polling the thread. A full
--save is one approval but re-measures every profile, and moves the untouched
ones by several percent of machine noise (gateway-64 +15%, production-stack
-4% in one run), so the real change arrives mixed with drift.
-t now accepts a comma-separated list, one job, one approval, one results
commit, and only the named profiles are touched:
/benchmark -f morojs -t gateway-h3,gateway-64,production-stack --save
benchmark.sh resolves the list at argument parsing, in the order given with
duplicates dropped, and a name that is not a profile fails there, before any
image is built or the host tuned; previously an explicit typo was warned past
and the run measured nothing while looking like a run. benchmark-lite.sh does
the same against its own table. compare.sh filters on the set.
pr-commands.yml checks every name in the list with the same pattern as
before. A list with a name that fails the check is rejected with a comment
instead of being reduced to an empty profile: an empty profile means "all
tests", and with --save that dispatched a full run nobody asked for, which is
exactly how an illustrative example in a PR comment on #1699 queued one. The
all-frameworks resolution in both workflows subscribes a framework when it
runs any profile in the list; benchmark.sh skips the ones it does not.
README, the PR template and the running-locally docs gain the list form.
… pinned to 26.13 gateway-h3 was never the server. Every entry fronted by Caddy lands at 56-63K at 256 connections with a p99 near 800 ms whatever the backend (cnetmod, trillium, roadrunner, libuvcpp, vanilla-epoll, this entry), while the entries on an nginx QUIC edge run at 175-200K; fulmine's own move to nginx (MDA2AV#1665) took it from 79K to 193K. The h3 edge is now stock nginx:1.27-alpine with http3 on udp 8443, the same configuration as the gateway-64 edge plus the quic listen, one worker per CPU of its cpuset. Caddy is gone from the entry. All three edges listen on loopback with reuseport instead of the wildcard: the validator keeps the standalone container, whose HTTP/2 listener holds *:8443, up beside the stack, and a specific address wins the lookup (the same arrangement anole, plod and libuvcpp use). The engine serve-order experiment on the proxied stacks is withdrawn: the full run measured nothing from it, and the cause it was aimed at was the Caddy edge. The image pins node:26.13-trixie-slim by minor. The bench host builds against whatever node:26 it has cached, and the compression middleware's reused brotli encoder needs Node 26.11 or later, where an encoder reset keeps its parameters; json-comp measured 370K on brotli 3 with an encoder built per reply, against 30 us a body with one kept.
06260f0 to
9be7814
Compare
|
/benchmark -f morojs -t gateway-h3,json-comp,gateway-64,production-stack,echo-ws-pipeline,echo-ws,echo-ws-limited --save |
|
👋 Benchmark request received. A collaborator will review and approve the run. |
…stack,echo-ws-pipeline,echo-ws,echo-ws-limited [skip ci]
Benchmark ResultsFramework:
Composite score, main against this run, in the board's default view:
The results on main were measured in another session, so a few points up or down can be the machine and not the change. Full log |
… engine's own path The route-level compression() middleware on the native engine no longer wraps res.json per request; it hands its settings to the engine response and the reply takes the server's own buffered-response compression, the same one native call an uncompressed reply takes. The entry is unchanged in behaviour and bytes: brotli at quality 3, gzip at level 3 as a fallback, one kept encoder per setting per worker. Measured at one worker on the profile's request mix against the 1.8.19 build of this entry, the hand-off is worth 9 to 12% more requests per second; the wrapping path materialised the request headers, parsed Accept-Encoding twice and replaced two response methods per request. The dependency floor moves to 1.8.20 so a build never measures the older path by resolving a cached 1.8.19. The description and comments stop calling the compressor gzip and stop describing the brotli encoder as built per body, which has not been true since 1.8.19 on the Node this image pins.
|
/benchmark -f morojs -t json-comp,gateway-64,gateway-h3 --save |
|
👋 Benchmark request received. A collaborator will review and approve the run. |
Benchmark ResultsFramework:
Composite score, main against this run, in the board's default view:
The results on main were measured in another session, so a few points up or down can be the machine and not the change. Full log |
… pinned to 26.13
gateway-h3 was never the server. Every entry fronted by Caddy lands at 56-63K at 256 connections with a p99 near 800 ms whatever the backend (cnetmod, trillium, roadrunner, libuvcpp, vanilla-epoll, this entry), while the entries on an nginx QUIC edge run at 175-200K; fulmine's own move to nginx (#1665) took it from 79K to 193K. The h3 edge is now stock nginx:1.27-alpine with http3 on udp 8443, the same configuration as the gateway-64 edge plus the quic listen, one worker per CPU of its cpuset. Caddy is gone from the entry.
All three edges listen on loopback with reuseport instead of the wildcard: the validator keeps the standalone container, whose HTTP/2 listener holds *:8443, up beside the stack, and a specific address wins the lookup (the same arrangement anole, plod and libuvcpp use).
The engine serve-order experiment on the proxied stacks is withdrawn: the full run measured nothing from it, and the cause it was aimed at was the Caddy edge.
The image pins node:26.13-trixie-slim by minor. The bench host builds against whatever node:26 it has cached, and the compression middleware's reused brotli encoder needs Node 26.11 or later, where an encoder reset keeps its parameters; json-comp measured 370K on brotli 3 with an encoder built per reply, against 30 us a body with one kept.
Description
PR Commands — comment on this PR to trigger (requires collaborator approval):
/benchmark -f <framework>/benchmark -f <framework> -t <test>/benchmark -f <framework> --save/benchmark -f <framework> -t <test> --save/benchmark -f <framework> --compare <other>/benchmark-multiple -f <fw1>,<fw2>,...-tand--savetoo; saved results land in a single commit/benchmark-multiple --save-fneeded: benchmark and save every framework the PR touches/benchmark-test -t <test><test>and save the resultsFor
/benchmark, always specify-f <framework>; the flags combine in any order. Results come back as a comment with a per-profile table of RPS, p99, CPU and memory — one table per framework on multi runs. A new benchmark comment while a run is in flight queues behind it (one deep) instead of cancelling it. For multi-framework PRs (dependency bumps, same-language refactors) prefer/benchmark-multiple, which runs everything in a single job and commits all saved results together, so no run overwrites another.--compareworks on single-framework runs only.What the deltas are measured against. By default, this framework's own results published on
main- answering "did this change help?". When you are tuning a variant or a successor entry,--comparere-bases them on another entry instead:The reply states which baseline it used, and profiles the other framework does not run show
n/arather than a delta.Run benchmarks locally
You can validate and benchmark your framework locally with the lite script — no CPU pinning, fixed connection counts, all load generators run in Docker.
Requirements: Docker Engine on Linux. Load generators (gcannon, h2load, h2load-h3, wrk) are built as self-contained Docker images on first run.