You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Investigating why esrun trailed Bun/Deno on HTTP throughput showed it was
not a core-count gap — all three saturate ~one core under load — but a
per-request one: esrun's JS↔Rust op boundary cost ~29µs/request vs ~11µs
for the native runtimes. Four changes to the request path, measured by
ablation, bring it to ~20µs:
- Batch the accept loop: HttpServerProvider::next_request -> next_requests(
id, max) drains all already-queued requests in one op crossing, amortizing
the dispatch + promise-resolve + microtask checkpoint over the batch.
- Cross request metadata as a structured array, not a per-request JSON
string built char-by-char in Rust and JSON.parse'd in JS.
- Read the response body synchronously from the Response (Response._parts)
instead of the async arrayBuffer() round-trip.
- Reuse the host-validated absolute URL for the server Request instead of
re-parsing it (internal __serverRequest, gated by a closure-private symbol
so the public Request constructor's eager validation is unchanged).
Also switch bench/rps.sh from autocannon to oha/bombardier: Bun's own
bench/express README warns autocannon's node:http client can't push a fast
server hard enough to measure it, and indeed it had capped every runtime at
~35-40k, hiding the real spread (Bun/Deno ~83-85k, esrun ~49k, Node ~30k).
README + home-page req/s chart updated to the real oha numbers.
0 commit comments