Skip to content

morojs: gateway-h3 on the nginx QUIC edge; loopback TLS listens; Node… - #1699

Merged
MDA2AV merged 4 commits into
MDA2AV:mainfrom
M-Chris:morojs-gateway-h3
Nov 3, 2026
Merged

MDA2AV merged 4 commits into
MDA2AV:mainfrom
M-Chris:morojs-gateway-h3

Conversation

@M-Chris

@M-Chris M-Chris commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

… 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):

Command Description
/benchmark -f <framework> Run every test the framework subscribes to
/benchmark -f <framework> -t <test> Run one test only
/benchmark -f <framework> --save Run and save results (updates the leaderboard on merge)
/benchmark -f <framework> -t <test> --save Run one test and save results
/benchmark -f <framework> --compare <other> Measure the deltas against another framework instead of this one
/benchmark-multiple -f <fw1>,<fw2>,... Benchmark several frameworks in one run — takes -t and --save too; saved results land in a single commit
/benchmark-multiple --save No -f needed: benchmark and save every framework the PR touches
/benchmark-test -t <test> Benchmark all enabled frameworks subscribed to <test> and save the results

For /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. --compare works 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, --compare re-bases them on another entry instead:

/benchmark -f genhttp --compare genhttp-kestrel

The reply states which baseline it used, and profiles the other framework does not run show n/a rather 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.

./scripts/validate.sh <framework>
./scripts/benchmark-lite.sh <framework> baseline
./scripts/benchmark-lite.sh --load-threads 4 <framework>

Requirements: Docker Engine on Linux. Load generators (gcannon, h2load, h2load-h3, wrk) are built as self-contained Docker images on first run.

@M-Chris

M-Chris commented Nov 2, 2026

Copy link
Copy Markdown
Contributor Author

/benchmark -f morojs --save

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

👋 Benchmark request received. A collaborator will review and approve the run.

@nigrosimone

nigrosimone commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

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.

@M-Chris

M-Chris commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/benchmark -f morojs -t gateway-h3 --save

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

👋 Benchmark request received. A collaborator will review and approve the run.

@M-Chris

M-Chris commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/benchmark -f morojs -t json-comp --save

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

👋 Benchmark request received. A collaborator will review and approve the run.

@M-Chris

M-Chris commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/benchmark -f morojs -t gateway-64 --save

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

👋 Benchmark request received. A collaborator will review and approve the run.

@M-Chris

M-Chris commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/benchmark -f morojs -t production-stack --save

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

👋 Benchmark request received. A collaborator will review and approve the run.

@M-Chris

M-Chris commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/benchmark -f morojs -t echo-ws-pipeline --save

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

👋 Benchmark request received. A collaborator will review and approve the run.

@M-Chris

M-Chris commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/benchmark -f morojs -t echo-ws --save

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

👋 Benchmark request received. A collaborator will review and approve the run.

@M-Chris

M-Chris commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/benchmark -f morojs -t echo-ws-limited --save

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

👋 Benchmark request received. A collaborator will review and approve the run.

@M-Chris

M-Chris commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

@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
that changes the WebSocket path). The guidance is to save touched profiles one at a
time with -t, which I agree with: a full --save moves untouched cells by several
percent. But -t takes one profile, and a PR holds one pending run, so that is seven
comments, seven approvals, each waiting for a collaborator, each posted only after the
previous run finishes. In practice that is a day or more of polling the thread for a
change that runs in under an hour of machine time. That is why I had been posting the
full --save: one approval, done, at the cost of the noise you described.

Proposal: let -t take a comma-separated list, so one run and one approval cover
exactly the touched profiles, in one results commit:

/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.sh, and the input description in benchmark-pr.yml. Happy to send that PR if
you want it.

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

👋 Benchmark request received. A collaborator will review and approve the run.

@MDA2AV

MDA2AV commented Nov 3, 2026

Copy link
Copy Markdown
Owner

Ok, can you add that change to the benchmark script? Ill merge the pr and you can rebase here

MDA2AV pushed a commit that referenced this pull request Nov 3, 2026
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.
@M-Chris

M-Chris commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/benchmark -f morojs -t gateway-h3,json-comp,gateway-64,production-stack,echo-ws-pipeline,echo-ws,echo-ws-limited --save

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

👋 Benchmark request received. A collaborator will review and approve the run.

…stack,echo-ws-pipeline,echo-ws,echo-ws-limited [skip ci]
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

Framework: morojs | Test: gateway-h3,json-comp,gateway-64,production-stack,echo-ws-pipeline,echo-ws,echo-ws-limited

Test Conn RPS CPU Mem Δ RPS Δ Mem
gateway-h3 64 190,605 4720.8% 3.6GiB +130.9% +44.0%
gateway-h3 256 196,222 5214.9% 4.2GiB +230.4% +23.5%
json-comp 4096 372,281 6219.9% 9.8GiB +0.4% ~0%
json-comp 16384 367,429 6249.2% 10.1GiB -0.2% -1.0%
gateway-64 512 228,040 4694.8% 3.7GiB -5.3% -2.6%
gateway-64 1024 220,583 4643.7% 4.4GiB -4.3% -2.2%
production-stack 256 114,581 2957.5% 3.2GiB -3.1% ~0%
production-stack 1024 111,000 2923.6% 3.8GiB +5.2% -5.0%
echo-ws-pipeline 512 23,540,924 6714.1% 8.2GiB +10.7% ~0%
echo-ws-pipeline 4096 23,492,680 6784.4% 8.3GiB +9.8% ~0%
echo-ws-pipeline 16384 22,576,512 6172.9% 8.5GiB +10.1% ~0%
echo-ws 512 3,499,612 6454.6% 8.2GiB -1.2% -1.2%
echo-ws 4096 3,620,352 6317.0% 8.3GiB +0.2% ~0%
echo-ws 16384 3,234,469 6452.6% 8.4GiB +0.7% +1.2%
echo-ws-limited 512 1,902,633 5805.5% 8.5GiB ~0% ~0%
echo-ws-limited 4096 2,384,193 6113.7% 8.6GiB +1.1% ~0%

Composite score, main against this run, in the board's default view:

Family main this run Δ
HTTP/1.1 6200.3 (8 of 104) 6201.2 (8 of 104) +1.0
HTTP/2 922.4 (17 of 38) 922.4 (17 of 38) +0.0
Gateway 1719.3 (5 of 9) 2307.0 (2 of 9) +587.7
WebSocket 2150.6 (8 of 36) 2193.8 (8 of 36) +43.1

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
  Bandwidth:  21.99MB/s
  WS upgrades: 16384
  WS frames:   16172346
  Latency samples: 16172346 / 16172346 responses (100.0%)
[info] CPU 6452.6% | Mem 8.4GiB

[run 3/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   5.04ms   4.69ms   7.41ms   10.00ms   12.50ms

  16150176 frames sent in 5.00s, 16133792 frames received
  Throughput: 3.23M req/s
  Bandwidth:  21.93MB/s
  WS upgrades: 16384
  WS frames:   16133792
  Latency samples: 16133792 / 16133792 responses (100.0%)
[info] CPU 6035.2% | Mem 8.3GiB

=== Best: 3234469 req/s (CPU: 6452.6%, Mem: 8.4GiB) ===
[info] saved results/echo-ws/16384/morojs.json
httparena-bench-morojs
httparena-bench-morojs

==============================================
=== morojs / echo-ws-limited / 512c (tool=gcannon) ===
==============================================
[info] waiting for server...
[info] server ready

[run 1/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     512 (8/thread)
  Pipeline:  1
  Req/conn:  10
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    209us    147us    352us   1.02ms   5.69ms

  8418070 frames sent in 5.00s, 8417965 frames received
  Throughput: 1.68M req/s
  Bandwidth:  31.94MB/s
  WS upgrades: 842192
  WS frames:   8417965
  Latency samples: 8417965 / 8417965 responses (100.0%)
  Reconnects: 841677
[info] CPU 5820.2% | Mem 8.5GiB

[run 2/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     512 (8/thread)
  Pipeline:  1
  Req/conn:  10
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    174us    142us    321us    645us   1.23ms

  9513082 frames sent in 5.00s, 9513165 frames received
  Throughput: 1.90M req/s
  Bandwidth:  36.10MB/s
  WS upgrades: 963293
  WS frames:   9513165
  Latency samples: 9513135 / 9513165 responses (100.0%)
  Reconnects: 951348
[info] CPU 5805.5% | Mem 8.5GiB

[run 3/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     512 (8/thread)
  Pipeline:  1
  Req/conn:  10
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    167us    136us    307us    618us   1.17ms

  9440651 frames sent in 5.00s, 9443385 frames received
  Throughput: 1.89M req/s
  Bandwidth:  35.83MB/s
  WS upgrades: 957082
  WS frames:   9443385
  Latency samples: 9440705 / 9443385 responses (100.0%)
  Reconnects: 944114
[info] CPU 5574.8% | Mem 8.5GiB

=== Best: 1902633 req/s (CPU: 5805.5%, Mem: 8.5GiB) ===
[info] saved results/echo-ws-limited/512/morojs.json
httparena-bench-morojs
httparena-bench-morojs

==============================================
=== morojs / echo-ws-limited / 4096c (tool=gcannon) ===
==============================================
[info] waiting for server...
[info] server ready

[run 1/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  10
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   1.48ms   1.08ms   2.60ms   7.72ms   29.80ms

  10363116 frames sent in 5.00s, 10360063 frames received
  Throughput: 2.07M req/s
  Bandwidth:  39.36MB/s
  WS upgrades: 1038125
  WS frames:   10360063
  Latency samples: 10360063 / 10360063 responses (100.0%)
  Reconnects: 1034626
[info] CPU 6265.5% | Mem 8.6GiB

[run 2/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  10
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   1.27ms   1.07ms   2.35ms   4.45ms   7.67ms

  11851759 frames sent in 5.00s, 11850445 frames received
  Throughput: 2.37M req/s
  Bandwidth:  44.99MB/s
  WS upgrades: 1190268
  WS frames:   11850445
  Latency samples: 11850438 / 11850445 responses (100.0%)
  Reconnects: 1184426
[info] CPU 6364.1% | Mem 8.6GiB

[run 3/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  10
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   1.27ms   1.07ms   2.35ms   4.26ms   7.21ms

  11920954 frames sent in 5.00s, 11920965 frames received
  Throughput: 2.38M req/s
  Bandwidth:  45.23MB/s
  WS upgrades: 1197978
  WS frames:   11920965
  Latency samples: 11920943 / 11920965 responses (100.0%)
  Reconnects: 1191867
[info] CPU 6113.7% | Mem 8.6GiB

=== Best: 2384193 req/s (CPU: 6113.7%, Mem: 8.6GiB) ===
[info] saved results/echo-ws-limited/4096/morojs.json
httparena-bench-morojs
httparena-bench-morojs
[info] rebuilding site/data/*.json
[purged stale] pyronova.json (pyronova)
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/frameworks.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/results/morojs.json - 16 new, 37 total
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/current.json
[info] done
httparena-postgres
[info] restoring loopback MTU to 65536

… 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.
@M-Chris

M-Chris commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/benchmark -f morojs -t json-comp,gateway-64,gateway-h3 --save

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

👋 Benchmark request received. A collaborator will review and approve the run.

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

Framework: morojs | Test: json-comp,gateway-64,gateway-h3

Test Conn RPS CPU Mem Δ RPS Δ Mem
json-comp 4096 436,734 6519.4% 9.9GiB +17.8% +1.0%
json-comp 16384 430,900 6262.9% 10.0GiB +17.1% -2.0%
gateway-64 512 281,802 5625.7% 3.7GiB +17.0% -2.6%
gateway-64 1024 280,712 5852.3% 4.3GiB +21.8% -4.4%
gateway-h3 64 185,827 5193.7% 3.4GiB +125.1% +36.0%
gateway-h3 256 193,319 4979.5% 4.2GiB +225.5% +23.5%

Composite score, main against this run, in the board's default view:

Family main this run Δ
HTTP/1.1 6200.3 (8 of 104) 6317.2 (7 of 104) +116.9
HTTP/2 922.4 (17 of 38) 922.4 (17 of 38) +0.0
Gateway 1719.3 (5 of 9) 2485.4 (1 of 9) +766.1
WebSocket 2150.6 (8 of 36) 2193.8 (8 of 36) +43.1

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
#10 CACHED

#11 [server build 2/4] WORKDIR /app
#11 CACHED

#12 [server build 4/4] RUN npm install --omit=dev --no-audit --no-fund
#12 CACHED

#13 [server stage-1 4/5] COPY app.mjs .
#13 CACHED

#14 [server build 3/4] COPY package.json .
#14 CACHED

#15 [server stage-1 5/5] COPY views ./views
#15 CACHED

#16 [proxy 1/4] FROM docker.io/library/nginx:1.27-alpine@sha256:65645c7bb6a0661892a8b03b89d0743208a18dd2f3f17a54ef4b76fb8e2f2a10
#16 resolve docker.io/library/nginx:1.27-alpine@sha256:65645c7bb6a0661892a8b03b89d0743208a18dd2f3f17a54ef4b76fb8e2f2a10 0.1s done
#16 DONE 0.1s

#17 [proxy internal] load build context
#17 transferring context: 62B done
#17 DONE 0.0s

#18 [server] exporting to image
#18 exporting layers done
#18 exporting manifest sha256:da80752f46ec30e9693ddb41a87f2ce663cb27f80eb22deb4293480814566a97 done
#18 exporting config sha256:b22fb783a68ecf95fab40bf08001c3334b8d1d82e833e6d7eae43d598f22cf69 done
#18 exporting attestation manifest sha256:78b8aa002e821952cc47340e4865f12a26d7167568b4a6eb4747b5430fcac0b9
#18 ...

#19 [proxy 2/4] COPY nginx.conf /etc/nginx/nginx.conf
#19 CACHED

#20 [proxy 3/4] COPY workers.sh /docker-entrypoint.d/30-workers.sh
#20 CACHED

#21 [proxy 4/4] RUN chmod +x /docker-entrypoint.d/30-workers.sh
#21 CACHED

#18 [server] exporting to image
#18 exporting attestation manifest sha256:78b8aa002e821952cc47340e4865f12a26d7167568b4a6eb4747b5430fcac0b9 0.1s done
#18 exporting manifest list sha256:e7871e3f0b34c95b67e27ed4a8140626a331cae2c1155c7e32ecd4c194d3abb3 0.0s done
#18 naming to docker.io/library/httparena-morojs-gateway-h3-server:latest 0.0s done
#18 unpacking to docker.io/library/httparena-morojs-gateway-h3-server:latest 0.0s done
#18 DONE 0.2s

#22 [proxy] exporting to image
#22 exporting layers done
#22 exporting manifest sha256:7bd0e3d42f9c50fdab1bf772fb41ab6ba8587af11e5237784b794709b3354409 0.0s done
#22 exporting config sha256:bbd44e1951c4d8eda012cef44c3dae3b2158f2174ff03b4851e00b29a86eac0d 0.0s done
#22 exporting attestation manifest sha256:f8f4a4903bfdf00a31da541d8c69bdd9cc42fdaa6d2c54b8a32db03ac8ffeb87 0.1s done
#22 exporting manifest list sha256:7e577eb0202c078ff3a9aa8a51e47114a180384c5d11dc241164a62545a18fca 0.1s done
#22 naming to docker.io/library/httparena-morojs-gateway-h3-proxy:latest
#22 naming to docker.io/library/httparena-morojs-gateway-h3-proxy:latest 0.0s done
#22 unpacking to docker.io/library/httparena-morojs-gateway-h3-proxy:latest 0.0s done
#22 DONE 0.2s

#23 [server] resolving provenance for metadata file
#23 DONE 0.0s

#24 [proxy] resolving provenance for metadata file
#24 DONE 0.0s
 Image httparena-morojs-gateway-h3-server Built 
 Image httparena-morojs-gateway-h3-proxy Built 
 Container httparena-morojs-gateway-h3-server-1 Creating 
 Container httparena-morojs-gateway-h3-server-1 Created 
 Container httparena-morojs-gateway-h3-proxy-1 Creating 
 Container httparena-morojs-gateway-h3-proxy-1 Created 
 Container httparena-morojs-gateway-h3-server-1 Starting 
 Container httparena-morojs-gateway-h3-server-1 Started 
 Container httparena-morojs-gateway-h3-proxy-1 Starting 
 Container httparena-morojs-gateway-h3-proxy-1 Started 
[info] gateway containers: 2 (0d5f9b3e7f1b 551a6e5c9614 )
[info] waiting for server...
[info] server ready

[run 1/3]
starting benchmark...
14.
.
.
TLS Protocol: TLSv1.3
Cipher: TLS_AES_128_GCM_SHA256
Server Temp Key: X25519 253 bits
Certificate: RSA 2048 bits
Negotiated Group: x25519
Resumption: no
Application protocol: h3
.


finished in 5.03s, 191627.20 req/s, 2.30GB/s
requests: 958136 total, 966328 started, 958136 done, 958136 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 958401 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 11.50GB (12351080284) total, 101.33MB (106255023) headers (space savings 36.78%), 11.40GB (12236233039) data
UDP datagram: 2623902 sent, 8734363 received
                 min         max         median     p95        p99        mean         sd        +/- sd
request     :      103us       3.18s     35.08ms   106.94ms   199.93ms    43.44ms     42.57ms    91.63%
connect     :     4.91ms     37.48ms     16.91ms    28.77ms    36.88ms    17.12ms      6.55ms    71.09%
TTFB        :    11.05ms     59.11ms     30.57ms    53.04ms    56.53ms    31.71ms     11.62ms    64.06%
req/s       :      95.40     3228.88      680.76    1412.54    2802.76     748.46      389.80    90.23%
min RTT     :        0us     27.76ms      1.62ms     7.96ms     9.69ms     2.70ms      3.11ms    82.03%
smoothed RTT:     2.66ms    333.00ms     16.00ms    21.18ms    23.03ms    17.02ms     20.17ms    99.61%
packets sent:       1339       44464        9271      18329      35224   10251.62     5235.84    91.02%
packets recv:       4626      146376       31025      64350     127192   34119.61    17666.15    90.23%
packets lost:          0         135         115        128        132     105.56       26.74    87.11%
GRO packets :          1           1           1          1          1       1.00        0.00   100.00%
[info] CPU 5357.1% | Mem 4.0GiB
[info]   proxy: 3204% 1.3GiB | server: 2153% 2.7GiB

[run 2/3]
starting benchmark...
.
30.
16.
TLS Protocol: TLSv1.3
Cipher: TLS_AES_128_GCM_SHA256
Server Temp Key: X25519 253 bits
Certificate: RSA 2048 bits
Negotiated Group: x25519
Resumption: no
Application protocol: h3
49.Main benchmark duration is started for thread #19.

52Main benchmark duration is started for thread #51.
.
8. Stopping all clients.Stopped all clients for thread #18

26. Stopping all clients.
24. Stopping all clients.
. Stopping all clients.
51. Stopping all clients.

finished in 5.03s, 193739.00 req/s, 2.33GB/s
requests: 968695 total, 976887 started, 968695 done, 968695 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 968965 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 11.63GB (12488473461) total, 102.45MB (107425876) headers (space savings 36.78%), 11.52GB (12372262280) data
UDP datagram: 2783534 sent, 8834625 received
                 min         max         median     p95        p99        mean         sd        +/- sd
request     :     1.95ms       4.60s     34.34ms    95.03ms   158.39ms    42.08ms     44.78ms    93.66%
connect     :     3.59ms     30.10ms     13.20ms    24.08ms    29.77ms    13.79ms      4.79ms    72.27%
TTFB        :     9.99ms     46.56ms     24.01ms    39.78ms    43.56ms    25.03ms      7.87ms    65.23%
req/s       :      53.00     1366.46      708.14    1272.47    1321.73     756.71      238.41    71.48%
min RTT     :        0us     10.63ms      4.93ms     7.69ms     9.21ms     4.81ms      1.87ms    65.63%
smoothed RTT:     9.39ms    333.00ms     15.11ms    20.67ms    22.92ms    17.71ms     28.18ms    99.22%
packets sent:        915       20099       10322      18085      19408   10875.18     3396.40    70.31%
packets recv:       2652       62207       32360      57814      60254   34511.25    10808.58    71.09%
packets lost:         25         156         126        145        152     121.31       20.59    79.30%
GRO packets :          1           1           1          1          1       1.00        0.00   100.00%
[info] CPU 5058.7% | Mem 4.1GiB
[info]   proxy: 3287% 1.4GiB | server: 1772% 2.7GiB

[run 3/3]
starting benchmark...
.
.Main benchmark duration is started for thread #63.

26.
TLS Protocol: TLSv1.3
Cipher: TLS_AES_128_GCM_SHA256
Server Temp Key: X25519 253 bits
Certificate: RSA 2048 bits
Negotiated Group: x25519
Resumption: no
Application protocol: h3
57. Stopping all clients.
41Stopped all clients for thread #32
. Stopping all clients.

finished in 5.03s, 194424.80 req/s, 2.33GB/s
requests: 972124 total, 980316 started, 972124 done, 972124 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 972395 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 11.67GB (12528885686) total, 102.81MB (107804083) headers (space savings 36.78%), 11.56GB (12412267745) data
UDP datagram: 2855569 sent, 8864024 received
                 min         max         median     p95        p99        mean         sd        +/- sd
request     :     1.53ms       2.90s     34.16ms    96.89ms   174.79ms    42.31ms     46.87ms    93.81%
connect     :     2.39ms       1.01s     14.05ms    22.24ms    36.73ms    18.38ms     62.42ms    99.61%
TTFB        :     5.26ms       1.02s     25.40ms    45.31ms    53.82ms    30.07ms     62.78ms    99.61%
req/s       :     258.36     2371.64      728.52    1415.49    1848.12     759.40      303.22    80.47%
min RTT     :      408us     12.39ms      4.99ms     8.58ms    10.22ms     5.02ms      2.16ms    65.23%
smoothed RTT:     3.02ms     23.83ms     15.23ms    21.03ms    23.44ms    15.36ms      3.36ms    74.22%
packets sent:       3916       34350       10501      20337      27261   11156.57     4418.71    80.08%
packets recv:      12039      107662       33300      64437      84155   34626.09    13750.13    80.86%
packets lost:          0         154         129        145        148     122.20       23.71    85.94%
GRO packets :          1           1           1          1          1       1.00        0.00   100.00%
[info] CPU 4979.5% | Mem 4.2GiB
[info]   proxy: 3275% 1.4GiB | server: 1705% 2.7GiB

=== Best: 193319 req/s (CPU: 4979.5%, Mem: 4.2GiB) ===
[info] saved results/gateway-h3/256/morojs.json
[info] rebuilding site/data/*.json
[purged stale] pyronova.json (pyronova)
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/frameworks.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/results/morojs.json - 6 new, 37 total
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/current.json
[info] done
httparena-postgres
[info] restoring loopback MTU to 65536

@MDA2AV
MDA2AV merged commit f0cd53c into MDA2AV:main Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants