perf(h1): deliver fixed-length response bodies without copying into wasm#5523
Open
mcollina wants to merge 2 commits into
Open
perf(h1): deliver fixed-length response bodies without copying into wasm#5523mcollina wants to merge 2 commits into
mcollina wants to merge 2 commits into
Conversation
Pause llhttp right after the headers of a response with a known content-length and hand the body bytes straight to the request, skipping the copy into wasm memory and llhttp's byte scan. While waiting for headers, feed llhttp bounded 4KB slices so the body bytes sharing a chunk with the headers are not copied either. At the message boundary llhttp is re-synchronized with llhttp_reset; trailing bytes are unshifted onto the socket and parsed normally. The fast path only activates for plain content-length framing: transfer-encoding, HEAD, CONNECT/upgrade, 1xx/204/304 and user-paused responses keep the existing llhttp path. Truncation is detected explicitly since llhttp_finish cannot see bytes it never parsed. readMore() is now guarded against re-entrancy so a resume triggered inside onMessageComplete cannot consume socket data before the completing frame has settled pipeline state. Benchmarks (local, Client x4, pipelining 10, GET, CPU per request via process.cpuUsage): body | req/s | CPU/request 64B | unchanged | unchanged 64KB | +5-9% | -3-7% 1MB | +17% | -10% (-16% user CPU) Signed-off-by: Matteo Collina <hello@matteocollina.com>
BODY_SIZE selects the response payload (default unchanged at 64KB) and TIMEOUT=0 now responds synchronously instead of falling back to 1ms, so both small-response and bulk-transfer workloads can be measured with the same server. Signed-off-by: Matteo Collina <hello@matteocollina.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5523 +/- ##
==========================================
+ Coverage 93.44% 93.47% +0.02%
==========================================
Files 110 110
Lines 37329 37526 +197
==========================================
+ Hits 34883 35077 +194
- Misses 2446 2449 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
This relates to...
N/A
Rationale
Reduce CPU and memory-copy overhead when receiving HTTP/1.1 responses with a known fixed content length by delivering body bytes directly to the request instead of copying them through the wasm llhttp parser.
Changes
readMore()against re-entrant reads while completing a response.benchmarks/server.jsconfigurable for response body size and synchronous responses.Features
N/A
Bug Fixes
N/A
Breaking Changes and Deprecations
N/A
Validation
git diff --check origin/main..HEADnpx eslint lib/dispatcher/client-h1.js test/client-content-length-fastpath.js benchmarks/server.jsnode --test test/client-content-length-fastpath.jsStatus