Skip to content

Bun: Do not use dynamic function for pipeline handler - #1309

Merged
MDA2AV merged 2 commits into
MDA2AV:mainfrom
uNetworkingAB:patch-1
Aug 25, 2026
Merged

Bun: Do not use dynamic function for pipeline handler#1309
MDA2AV merged 2 commits into
MDA2AV:mainfrom
uNetworkingAB:patch-1

Conversation

@uNetworkingAB

Copy link
Copy Markdown
Contributor

Description

Performance optimal fix


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-11 --compare genhttp-11-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.

@MDA2AV

MDA2AV commented Aug 25, 2026

Copy link
Copy Markdown
Owner

/benchmark --save

@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

Copy link
Copy Markdown
Contributor

Benchmark Results

Framework: bun | Test: all tests

Test Conn RPS CPU Mem Δ RPS Δ Mem
baseline 512 1,784,077 6736.9% 1.3GiB -1.2% ~0%
baseline 4096 1,918,558 6565.5% 1.2GiB -0.8% ~0%
pipelined 512 5,000,374 6523.7% 420MiB +5401.1% -23.6%
pipelined 4096 5,417,945 6619.1% 449MiB +1463.4% -48.0%
limited-conn 512 1,394,349 6315.6% 1.1GiB ~0% ~0%
limited-conn 4096 1,646,424 6578.1% 1.3GiB -0.2% +8.3%
json 4096 1,122,348 6333.5% 1.1GiB +0.2% ~0%
json-comp 512 428,765 6095.5% 1.1GiB -0.5% ~0%
json-comp 4096 464,909 6498.5% 1.1GiB +0.3% ~0%
json-comp 16384 466,079 6522.1% 1.2GiB -0.1% ~0%
json-tls 4096 1,077,848 6316.8% 1.0GiB +0.2% ~0%
upload 32 1,903 2993.9% 2.5GiB -0.5% +4.2%
upload 256 1,998 5901.9% 2.8GiB +0.5% +7.7%
api-4 256 43,441 389.3% 157MiB -0.4% +0.6%
api-16 1024 154,247 1513.3% 592MiB +1.0% -0.5%
static 1024 574,323 6531.0% 1.1GiB +0.1% ~0%
static 4096 568,905 6548.0% 1.1GiB -0.2% ~0%
static 6800 559,625 6566.0% 1.2GiB -0.2% ~0%
static-tls 1024 483,697 6570.3% 1.1GiB ~0% ~0%
static-tls 4096 472,705 6523.5% 1.1GiB ~0% ~0%
static-tls 6800 462,712 6396.5% 1.2GiB +0.3% ~0%
async-db 1024 281,632 5251.6% 2.2GiB +1.6% ~0%
crud 4096 310,978 2928.7% 1.5GiB -0.5% ~0%
fortunes 1024 82,955 6387.5% 2.0GiB -0.4% ~0%
Full log
  Conns:     1024 (16/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 5
  Expected:  200
  Duration:  10s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   3.44ms   1.94ms   7.97ms   21.10ms   36.30ms

  2549256 requests in 10.00s, 2549258 responses
  Throughput: 254.87K req/s
  Bandwidth:  976.03MB/s
  Status codes: 2xx=2549258, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 2549247 / 2549258 responses (100.0%)
  Reconnects: 101987
  Per-template: 508291,509671,511025,511342,508918
  Per-template-ok: 508291,509671,511025,511342,508918
[info] CPU 4825.4% | Mem 1.9GiB

=== Best: 281632 req/s (CPU: 5251.6%, Mem: 2.2GiB) ===
[info] input BW: 18.80MB/s (avg template: 70 bytes)
[info] saved results/async-db/1024/bun.json
httparena-bench-bun
httparena-bench-bun

==============================================
=== bun / crud / 4096c (tool=gcannon) ===
==============================================
[info] resetting postgres for a clean per-profile baseline
[info] starting postgres sidecar
httparena-postgres
[info] postgres ready (seeded)
[info] waiting for server...
[info] server ready

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


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   13.44ms   13.80ms   17.70ms   26.60ms   40.20ms

  4554325 requests in 15.00s, 4554005 responses
  Throughput: 303.55K req/s
  Bandwidth:  102.60MB/s
  Status codes: 2xx=4554005, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 4554004 / 4554005 responses (100.0%)
  Reconnects: 21306
  Per-template: 249257,279332,265729,239454,240382,235716,206759,207290,207517,206851,206233,206231,206748,206735,206953,206734,242718,245663,244283,243419
  Per-template-ok: 249257,279332,265729,239454,240382,235716,206759,207290,207517,206851,206233,206231,206748,206735,206953,206734,242718,245663,244283,243419
[info] CPU 3014.5% | Mem 1.7GiB

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


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   13.18ms   13.60ms   17.40ms   24.60ms   41.30ms

  4628488 requests in 15.00s, 4628292 responses
  Throughput: 308.50K req/s
  Bandwidth:  103.69MB/s
  Status codes: 2xx=4628292, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 4628289 / 4628292 responses (100.0%)
  Reconnects: 22202
  Per-template: 260631,282547,279956,243400,244104,244707,209559,209055,209441,209439,209778,209534,209304,208834,208448,208760,240809,247302,247307,245374
  Per-template-ok: 260631,282547,279956,243400,244104,244707,209559,209055,209441,209439,209778,209534,209304,208834,208448,208760,240809,247302,247307,245374
[info] CPU 2834.6% | Mem 1.5GiB

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


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   13.09ms   13.50ms   17.40ms   25.00ms   33.80ms

  4664938 requests in 15.00s, 4664682 responses
  Throughput: 310.93K req/s
  Bandwidth:  104.52MB/s
  Status codes: 2xx=4664682, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 4664670 / 4664682 responses (100.0%)
  Reconnects: 22504
  Per-template: 271927,284089,281258,244700,244874,245278,210241,209157,209972,210026,210671,210810,210808,210640,210792,210962,243474,249480,248428,247083
  Per-template-ok: 271926,284089,281258,244700,244874,245278,210241,209157,209972,210026,210671,210810,210808,210640,210792,210962,243474,249480,248428,247083
[info] CPU 2928.7% | Mem 1.5GiB

=== Best: 310978 req/s (CPU: 2928.7%, Mem: 1.5GiB) ===
[info] input BW: 26.69MB/s (avg template: 90 bytes)
[info] saved results/crud/4096/bun.json
httparena-bench-bun
httparena-bench-bun

==============================================
=== bun / fortunes / 1024c (tool=gcannon) ===
==============================================
[info] resetting postgres for a clean per-profile baseline
[info] starting postgres sidecar
httparena-postgres
[info] postgres ready (seeded)
[info] waiting for server...
[info] server ready

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


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   9.14ms   8.57ms   15.00ms   23.30ms   36.90ms

  409499 requests in 5.00s, 409499 responses
  Throughput: 81.87K req/s
  Bandwidth:  1.89GB/s
  Status codes: 2xx=409499, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 409499 / 409499 responses (100.0%)
[info] CPU 6282.2% | Mem 2.0GiB

[run 2/3]
timeout: the monitored command dumped core
[info] CPU 6441.4% | Mem 2.0GiB

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


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   8.94ms   8.48ms   14.40ms   20.90ms   26.30ms

  414777 requests in 5.00s, 414777 responses
  Throughput: 82.92K req/s
  Bandwidth:  1.91GB/s
  Status codes: 2xx=414777, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 414773 / 414777 responses (100.0%)
[info] CPU 6387.5% | Mem 2.0GiB

=== Best: 82955 req/s (CPU: 6387.5%, Mem: 2.0GiB) ===
[info] saved results/fortunes/1024/bun.json
httparena-bench-bun
httparena-bench-bun
[info] skip: bun does not subscribe to baseline-h2
[info] skip: bun does not subscribe to static-h2
[info] skip: bun does not subscribe to baseline-h2c
[info] skip: bun does not subscribe to json-h2c
[info] skip: bun does not subscribe to baseline-h3
[info] skip: bun does not subscribe to static-h3
[info] skip: bun does not subscribe to gateway-64
[info] skip: bun does not subscribe to gateway-h3
[info] skip: bun does not subscribe to production-stack
[info] skip: bun does not subscribe to unary-grpc
[info] skip: bun does not subscribe to unary-grpc-tls
[info] skip: bun does not subscribe to echo-ws
[info] skip: bun does not subscribe to echo-ws-pipeline
[info] skip: bun does not subscribe to echo-ws-limited
[info] rebuilding site/data/*.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/frameworks.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/results/bun.json - 24 new, 24 total
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/current.json
[info] done
httparena-postgres
httparena-redis
[info] restoring loopback MTU to 65536

@MDA2AV
MDA2AV merged commit fbf3907 into MDA2AV:main Aug 25, 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.

2 participants