perf(vanilla-epoll): serve /static via static_assets (precompressed negotiation)#954
Open
enghitalo wants to merge 2 commits into
Open
perf(vanilla-epoll): serve /static via static_assets (precompressed negotiation)#954enghitalo wants to merge 2 commits into
enghitalo wants to merge 2 commits into
Conversation
…egotiation) The /static handler hand-rolled a second static path: it preloaded ONLY the identity files (skipping the .br/.gz siblings) and never read Accept-Encoding, so it always shipped the uncompressed body. The static profile sends `Accept-Encoding: br;q=1, gzip;q=0.8`, so vanilla-epoll was sending ~4x the bytes of servers that serve the precompressed sibling (≈2x bandwidth, ≈half the rps). Replace it with the lib's audited static_assets module, mounted at /static/ via the new `url_prefix` (enghitalo/vanilla#80): one implementation that negotiates the .br/.gz sibling, sets ETag/Vary/Cache-Control, and streams large assets with sendfile(2) — emitted through the same core.queue_file handoff the worker already drains. Drops the duplicate StaticFile/static_header/content_type/C.open. Local A/B (server pinned to 2 cores, wrk + static-rotate.lua, br;q=1, both CPU- saturated): identity-only ~56.8K req/s @ 3.37 GB/s -> static_assets ~104K req/s @ 1.60 GB/s (+83% rps, -52% bandwidth) at equal CPU. curl-verified: /static/app.js + Accept-Encoding: br -> Content-Encoding: br, 47,275 B (vs 204,800 identity); .woff2 (no sibling) -> identity; traversal -> 404. Bumps the vanilla pin to main + MDA2AV#80 (url_prefix). kTLS/MDA2AV#79 and queue_buf/MDA2AV#75 ride along on main but are inert here (no -d vanilla_tls; queue_buf unused by epoll). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 29, 2026
Contributor
Author
|
Dependency satisfied: enghitalo/vanilla#80 ( |
…merged) Both lib deps are now on vanilla main: enghitalo/vanilla#80 (static_assets url_prefix) and MDA2AV#81 (core.queue_buf borrowed send). Repin from the MDA2AV#80 branch commit to the merged main commit. No entry change; rebuilds clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Author
|
/benchmark -f vanilla-epoll |
Contributor
|
👋 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
vanilla-epollloses thestaticprofile by a wide margin — and the bandwidth column shows exactly why:~2× the bandwidth at ~half the rps. The
/statichandler preloaded only the identity files (it skipped the.br/.gzsiblings) and never readAccept-Encoding, so it always shipped the uncompressed body. The profile sendsAccept-Encoding: br;q=1, gzip;q=0.8, so the leaders serve the ~4× smaller.brsibling and vanilla was sending the full file.It was also a second, hand-rolled static path — the lib already ships an audited
static_assetsmodule that does precompressed negotiation + ETag/conditional +Vary+sendfile(2)correctly, but the entry didn't use it.Change
Serve
/static/*throughstatic_assets, mounted at/static/via the newurl_prefix(depends on enghitalo/vanilla#80). One audited implementation; drops the duplicateStaticFile/static_header/content_type/C.open. Emits via the samecore.queue_filesendfile handoff the worker already drains.Evidence
Local A/B, server pinned to 2 cores,
wrk+ this repo'sstatic-rotate.lua(Accept-Encoding: br;q=1), both CPU-saturated:/statichandlerstatic_assets(this PR)+83% rps, −52% bandwidth at equal CPU — the precompressed body is the whole difference (mirrors the published zix-vs-vanilla static signature). curl-verified correctness:
/static/app.js+Accept-Encoding: br→Content-Encoding: br, 47,275 B (vs 204,800 identity);.woff2(no sibling) → identity;..traversal → 404;gzip-only →.gz.Pin
Bumps the vanilla pin to main + enghitalo/vanilla#80 (
url_prefix). enghitalo/vanilla#75 (core.queue_buf) and enghitalo/vanilla#79 (kTLS) ride along on main but are inert in this image: it builds without-d vanilla_tls, andqueue_bufis unused by the epoll entry. Compiles clean (v -prod -gc none).🤖 Generated with Claude Code