Skip to content

fix(vanilla-io_uring): lazy json-comp gz cache (parity + drop pointless boot precompute)#960

Open
enghitalo wants to merge 2 commits into
MDA2AV:mainfrom
enghitalo:fix/json-comp-iouring-lazy
Open

fix(vanilla-io_uring): lazy json-comp gz cache (parity + drop pointless boot precompute)#960
enghitalo wants to merge 2 commits into
MDA2AV:mainfrom
enghitalo:fix/json-comp-iouring-lazy

Conversation

@enghitalo

Copy link
Copy Markdown
Contributor

What

Restore the lazy, shared json-comp gz cache on vanilla-io_uring, reverting the lock-free boot precompute that shipped in #957.

(Split of #958 — this is the io_uring half; the epoll half is a separate PR.)

Why

This entry builds default-GC, so it did not leak (unlike the -gc none epoll sibling, where the precompute leaked ~135 MiB via vlang/v#27606). But the precompute is ~800 pointless gzip.compress calls at boot with no benefit, so this reverts it for parity with the epoll entry and to restore the validated pre-cleanup state. Adds a guard comment so it isn't reintroduced.

The lock-free change was meant to fix the io_uring json-comp@16384 collapse (enghitalo/vanilla#89), but CI refuted it: the collapse persists and is a separate, still-unexplained issue (low CPU at 16384c — not the lock). This PR does not claim to fix it.

Benchmark (already run on #958, vanilla-io_uring)

  • json-comp@16384: recovered from the collapsed 159K (the precompute run) to 402,286 rps (+152.5%) — still degraded (CPU 990%, not saturated), but better than with the precompute.
  • Memory unchanged (default GC, never leaked).
  • No throughput regression elsewhere.

Happy to re-run /benchmark -f vanilla-io_uring on this split PR to re-validate.

🤖 Generated with Claude Code

…ss boot precompute)

Restore the original LAZY, process-shared gz cache for json-comp, reverting the
lock-free boot precompute from MDA2AV#957.

This io_uring entry builds default-GC, so it did NOT leak (unlike the `-gc none` epoll
sibling, where the precompute leaked ~135 MiB via vlang/v#27606). But the precompute is
~800 pointless gzip.compress calls at boot with no benefit, so revert it for parity with
the epoll entry and to restore the validated pre-cleanup state. Adds a guard comment so
the precompute is not reintroduced.

The lock-free change was meant to fix the io_uring json-comp@16384 collapse
(enghitalo/vanilla#89), but CI refuted it: the collapse persists and is a separate,
still-unexplained issue (low CPU at 16384c — not the lock).

Validated (benchmarked as MDA2AV#958): json-comp@16384 recovered from the collapsed 159K
(the precompute run) to 402K rps (+152.5%) — still degraded but better than with the
precompute; memory unchanged (default GC). No throughput regression elsewhere.

Split out of MDA2AV#958 (one PR per engine).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@enghitalo

Copy link
Copy Markdown
Contributor Author

/benchmark -f vanilla-io_uring --save

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

Framework: vanilla-io_uring | Test: all tests

Test Conn RPS CPU Mem Δ RPS Δ Mem
baseline 512 3,275,759 6403.6% 1.5GiB -1.5% ~0%
baseline 4096 3,655,431 5411.7% 1.5GiB -4.2% ~0%
pipelined 512 35,812,195 6684.2% 987MiB -1.0% -3.6%
pipelined 4096 37,935,651 6488.3% 1.1GiB -0.6% ~0%
limited-conn 512 2,289,041 5388.2% 1.5GiB -0.4% +7.1%
limited-conn 4096 2,183,936 5029.1% 1.5GiB -3.5% -6.3%
json 4096 2,415,906 6379.9% 1.4GiB +0.3% ~0%
json-comp 512 2,082,103 6162.6% 1.0GiB -2.4% ~0%
json-comp 4096 2,844,764 6524.1% 1.4GiB -1.0% ~0%
json-comp 16384 155,961 484.9% 2.0GiB -2.1% ~0%
json-tls 4096 1,482,756 6066.8% 1.5GiB NEW NEW
upload 32 2,583 1849.9% 1.4GiB -1.3% +7.7%
upload 256 2,978 3411.6% 1.3GiB +0.6% -13.3%
api-4 256 28,434 356.8% 2.0GiB ~0% -4.8%
api-16 1024 28,450 1459.0% 2.1GiB -2.4% -8.7%
static 1024 1,448,199 5431.0% 1020MiB -0.3% -0.4%
static 4096 1,354,100 5423.5% 1.2GiB -0.3% ~0%
static 6800 1,233,134 5587.8% 1.4GiB -0.7% +16.7%
async-db 1024 11,025 5086.3% 1.8GiB +3.6% -5.3%
crud 4096 231,065 1458.0% 1.9GiB +4.4% +11.8%
fortunes 1024 37 966.9% 1.7GiB -47.1% +21.4%
Full log
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   22.06ms   16.40ms   35.70ms   175.40ms    1.00s

  2783669 requests in 15.00s, 2780789 responses
  Throughput: 185.36K req/s
  Bandwidth:  58.24MB/s
  Status codes: 2xx=2780789, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 2780789 / 2780789 responses (100.0%)
  Reconnects: 11911
  Per-template: 129822,135223,138559,142411,143337,145245,145342,137782,141414,142718,145506,145553,142613,142052,141665,139923,135651,132034,127114,126825
  Per-template-ok: 129822,135223,138559,142411,143337,145245,145342,137782,141414,142718,145506,145553,142613,142052,141665,139923,135651,132034,127114,126825
[info] CPU 1097.8% | Mem 1.6GiB

[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   18.91ms   15.60ms   32.70ms   175.20ms   211.50ms

  3219858 requests in 15.00s, 3219593 responses
  Throughput: 214.60K req/s
  Bandwidth:  68.00MB/s
  Status codes: 2xx=3219593, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 3219591 / 3219593 responses (100.0%)
  Reconnects: 14166
  Per-template: 149830,151527,156842,160970,166356,168923,167384,163068,163472,162408,162549,162487,162708,164789,167204,167734,165164,158729,151163,146284
  Per-template-ok: 149830,151527,156842,160970,166356,168923,167384,163068,163472,162408,162549,162487,162708,164789,167204,167734,165164,158729,151163,146284
[info] CPU 1383.5% | Mem 1.8GiB

[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   17.69ms   14.20ms   31.50ms   178.50ms   221.50ms

  3465984 requests in 15.00s, 3465984 responses
  Throughput: 231.03K req/s
  Bandwidth:  73.10MB/s
  Status codes: 2xx=3465984, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 3465979 / 3465984 responses (100.0%)
  Reconnects: 15393
  Per-template: 158600,163583,170585,174656,180054,180423,179578,181584,179206,181277,177713,173160,172816,175511,179745,182460,175175,164904,158700,156249
  Per-template-ok: 158600,163583,170585,174656,180054,180423,179578,181584,179206,181277,177713,173160,172816,175511,179745,182460,175175,164904,158700,156249
[info] CPU 1458.0% | Mem 1.9GiB

=== Best: 231065 req/s (CPU: 1458.0%, Mem: 1.9GiB) ===
[info] input BW: 19.83MB/s (avg template: 90 bytes)
[info] saved results/crud/4096/vanilla-io_uring.json
httparena-bench-vanilla-io_uring
httparena-bench-vanilla-io_uring

==============================================
=== vanilla-io_uring / 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    4.81s    4.81s    4.85s    4.85s    4.85s

  10 requests in 5.00s, 10 responses
  Throughput: 1 req/s
  Bandwidth:  48.54KB/s
  Status codes: 2xx=10, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 10 / 10 responses (100.0%)
[info] CPU 411.3% | Mem 1.1GiB

[run 2/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    3.03s    3.75s    4.51s    4.92s    4.92s

  88 requests in 5.00s, 88 responses
  Throughput: 17 req/s
  Bandwidth:  427.16KB/s
  Status codes: 2xx=88, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 88 / 88 responses (100.0%)
[info] CPU 994.9% | Mem 1.3GiB

[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    2.96s    3.53s    4.87s    4.99s    4.99s

  186 requests in 5.00s, 186 responses
  Throughput: 37 req/s
  Bandwidth:  902.86KB/s
  Status codes: 2xx=186, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 186 / 186 responses (100.0%)
[info] CPU 966.9% | Mem 1.7GiB

=== Best: 37 req/s (CPU: 966.9%, Mem: 1.7GiB) ===
[info] saved results/fortunes/1024/vanilla-io_uring.json
httparena-bench-vanilla-io_uring
httparena-bench-vanilla-io_uring
[info] skip: vanilla-io_uring does not subscribe to baseline-h2
[info] skip: vanilla-io_uring does not subscribe to static-h2
[info] skip: vanilla-io_uring does not subscribe to baseline-h2c
[info] skip: vanilla-io_uring does not subscribe to json-h2c
[info] skip: vanilla-io_uring does not subscribe to baseline-h3
[info] skip: vanilla-io_uring does not subscribe to static-h3
[info] skip: vanilla-io_uring does not subscribe to gateway-64
[info] skip: vanilla-io_uring does not subscribe to gateway-h3
[info] skip: vanilla-io_uring does not subscribe to production-stack
[info] skip: vanilla-io_uring does not subscribe to unary-grpc
[info] skip: vanilla-io_uring does not subscribe to unary-grpc-tls
[info] skip: vanilla-io_uring does not subscribe to stream-grpc
[info] skip: vanilla-io_uring does not subscribe to stream-grpc-tls
[info] skip: vanilla-io_uring does not subscribe to echo-ws
[info] skip: vanilla-io_uring does not subscribe to echo-ws-pipeline
[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/api-16-1024.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/api-4-256.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/async-db-1024.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/baseline-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/baseline-512.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/crud-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/fortunes-1024.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/json-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/json-comp-16384.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/json-comp-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/json-comp-512.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/json-tls-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/limited-conn-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/limited-conn-512.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/pipelined-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/pipelined-512.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/static-1024.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/static-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/static-6800.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/upload-256.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/upload-32.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/current.json
[info] done
httparena-postgres
httparena-redis
[info] restoring loopback MTU to 65536

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.

1 participant