Conversation
cursor
Bot
force-pushed
the
cursor/http-perf-a3fb
branch
2 times, most recently
from
September 19, 2026 03:01
fbe7035 to
1fda05a
Compare
Signed-off-by: Ayush Chaudhary <ayush23chaudhary@gmail.com> PR-URL: nodejs#64251 Fixes: nodejs#64230 Reviewed-By: René <contact.9a5d6388@renegade334.me.uk> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Add `Buffer.stringLength(input[, encoding])`, the counterpart of `Buffer.byteLength()`: it returns the number of UTF-16 code units that `buf.toString(encoding)` would produce, without decoding. For UTF-8 the count is computed with simdutf. Invalid input is counted with the same maximal-subpart replacement that the decoder applies, so the result always matches `toString().length`. The other encodings are computed from `byteLength` alone. This lets code that accumulates streamed input check the result against `buffer.constants.MAX_STRING_LENGTH` and size its memory budget before decoding. Refs: nodejs#66062 Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: nodejs#66064 Reviewed-By: Paolo Insogna <paolo@cowtech.it> Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
OpenSSL no longer applies DNS name constraints to the subject CN by default, but tls.checkServerIdentity() still uses it without a DNS SAN. Enable subject checking during chain verification only when no DNS SAN exists, preserving the existing hostname verification policy. Assisted-by: Codex Signed-off-by: Filip Skokan <panva.ip@gmail.com> PR-URL: nodejs#65957 Refs: https://openssl-library.org/post/2026-09-09-openssl-4.1-alpha/ Reviewed-By: Tim Perry <pimterry@gmail.com>
`inspector.Session#connectToMainThread()` in a Worker aborted the process on `CHECK_NOT_NULL(parent_handle_)` in `Agent::ConnectToMainThread()` when the parent Environment was created with `kNoCreateInspector`, as embedders that run their own inspector (or none) do. Throw the new `ERR_INSPECTOR_NOT_AVAILABLE` in that case, next to the existing throw for a Worker whose own inspector is not initialized. Refs: nodejs#35025 Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com> PR-URL: nodejs#65976 Reviewed-By: Kohei Ueno <kohei.ueno119@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Remove allocations and repeated work performed for every request: - reuse a per-connection updateOutgoingData closure and a shared 'finish' listener instead of binding two functions per request, reaching resOnFinish through the connection state stored on the response - cache the ServerResponse options object per server (custom response classes keep receiving a fresh object) - check for Host, Expect, Content-Length and Transfer-Encoding by scanning rawHeaders instead of materializing req.headers, which was built (with per-name toLowerCase calls) for every request even when the application never reads it - cache the rendered status line per status code when the reason phrase is the default, skipping its character validation - cache the complete 'Date: ...' header line in the utcDate cache and the keep-alive header pair for the current server settings - compute the lenient-validation option chain once per message Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: nodejs#65802 Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Tim Perry <pimterry@gmail.com> Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
After nodejs#65802, Host/Expect/body checks still allocate toLowerCase() copies and Expect/HTTP/1.0 TE still read req.headers. Compare names without allocating, read those values from rawHeaders, intern parser header names, and skip Title-Case toLowerCase on common outgoing fields. Refs: nodejs#65802 Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com> Assisted-by: a closed-source coding agent
cursor
Bot
force-pushed
the
cursor/http-perf-a3fb
branch
from
September 19, 2026 12:03
16a6107 to
9b786ff
Compare
Interning every parsed header name lets a client fill the V8 interned string table with unique tokens. Drop that and keep names as ordinary strings. Refs: nodejs#66120 Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com> Assisted-by: a closed-source coding agent
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.
What
Every HTTP/1.1 request was paying for work most applications never need:
requireHostHeader(on by default) and the Expect check both readreq.headers, which builds the whole headers object andtoLowerCase()s every name.writeHead()rebuilt the status line,Date:line, andKeep-Alivepair on every response.updateOutgoingData,resOnFinish).Hostthat appear on every request.This change:
rawHeaderswith a non-allocating ASCII compare for Host / Expect /Content-Length/Transfer-Encoding.Date: …\r\nline, and the Connection + Keep-Alive pair.'finish'listener per connection.kInternalized) so repeated tokens share one V8 string.Wire format is unchanged.
req.headersis still lazy and still correct when the application reads it, including unusualHOST/EXPECTcasing (test/parallel/test-http-server-raw-header-lookup.js).Benchmarks
Release build (
./configure --without-intl --without-npm), same machine, server pinned withtaskset -c 0, client iswrk -t2 -c50. Baseline is this tree atdd5dfb5250(currentnodejs/nodemain). Opt is this PR.Official Node benches (one 5s run each):
http/simple.jsbytes,len=4,c=50http/incoming_headers.jsheaders=20wrkhello-world, 8 extra request headers, 5 interleaved rounds of 8s (distributions do not overlap):res.end('hello')req.headers.hostThe extra-header case is the realistic one: browsers and proxies send Host plus several other fields, and
requireHostHeaderused to materialize all of them.Tests
python3 tools/test.py --mode=release --shell <opt-node>: alltest/parallel/test-http-*.jsthat I ran passed (408 files across three batches).Related
Overlaps with nodejs#65802 and nodejs#65332. Differences from nodejs#65802: the raw-header scan does not allocate
toLowerCase()copies, Expect is resolved without materializingreq.headers, HTTP/1.0TEuses the same path, and header names are interned in the parser.AI
A closed-source coding agent helped write and measure this. The HTTP hot path (
parserOnIncoming,_storeHeader,CreateHeaders) was read and checked against the existing tests before opening the PR. Benchmark numbers above are from the two release binaries on this machine, not from a model.Refs: nodejs#65802
Refs: nodejs#65332