Skip to content

url: speed up WHATWG URL parsing - #19

Draft
anonrig wants to merge 49 commits into
mainfrom
cursor/url-parse-performance-603e
Draft

url: speed up WHATWG URL parsing#19
anonrig wants to merge 49 commits into
mainfrom
cursor/url-parse-performance-603e

Conversation

@anonrig

@anonrig anonrig commented Aug 17, 2026

Copy link
Copy Markdown
Owner

What

Speeds up new URL() / URL.parse() on the common path: already-serialized ASCII hrefs.

The binding currently always:

  1. Copies the V8 string into a UTF-8 buffer (Utf8Value)
  2. Parses with Ada
  3. Allocates a new V8 string from href, even when it is byte-identical to the input

Typical URLs (https://example.com/path, the whatwg-url-parse benchmark corpus) are one-byte ASCII and already in serialized form. This change:

  • Parses one-byte ASCII inputs in place via v8::String::ValueView (no UTF-8 copy)
  • Returns the original V8 string when href == input (no second string allocation)
  • Avoids copying the base URL into a temporary std::string just to parse it
  • Applies the same in-place parse to update() (setters re-parse an already-serialized href)
  • Delays URLContext allocation until parse finishes, and initializes it in one shot from urlComponents
  • Skips `${input}` when the value is already a string

Non-ASCII inputs still go through Utf8Value. Those results are never reused as the original string, because UTF-8 conversion may replace unpaired surrogates.

Benchmark

Same machine, Release build, benchmark/url/whatwg-url-parse.js e=12. Repeated runs, same binary pair:

Config Before (ops/s) After (ops/s) Change
short / no base 7.82M 9.29M +19%
long / no base 2.50M 2.75M +10%
short / with base 2.94M 3.39M +15%

dot (needs path normalization, so a new href string) is unchanged.

Tests

  • test/parallel/test-whatwg-url-*.js and test-url-*.js: 54 pass, 1 skip
  • WPT url: 5107 pass, 0 unexpected failures
  • New test/parallel/test-whatwg-url-parse-fast-path.js covers already-serialized ASCII hrefs, trailing-slash and dot-segment normalization, base resolution, non-string input, invalid input, unpaired surrogates, IDN, and setters
Open in Web Open in Cursor 

nodejs-github-bot and others added 30 commits August 14, 2026 18:33
PR-URL: nodejs#65114
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Signed-off-by: ulofiai <monsterking@tutamail.com>
PR-URL: nodejs#65118
Fixes: nodejs#63638
Refs: libuv/libuv#5152
Refs: libuv/libuv@e640dc9
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: nodejs#65250
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Stewart X Addison <sxa@redhat.com>
Reviewed-By: Mike McCready <66998419+MikeMcC399@users.noreply.github.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Beth Griggs <bethanyngriggs@gmail.com>
Use undefined as the no-error sentinel when cancelling broadcast and
share consumers. This ensures that 0, an empty string, false, and null
are propagated instead of being converted to clean completion.

Make sync share surface cancellation reasons before handling detached
consumers, and add regression coverage for async and sync consumers.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: codex:gpt-5.6-sol
PR-URL: nodejs#64705
Fixes: nodejs#64704
Reviewed-By: James M Snell <jasnell@gmail.com>
SQLite requires that an authorizer callback not modify the connection
that invoked it, and counts sqlite3_prepare_v2() and sqlite3_step() as
modifications. node:sqlite let the callback call prepare(), exec(), the
statement execution methods, and other connection-mutating APIs on the
same DatabaseSync. Track authorizer depth on DatabaseSync with an RAII
guard around the callback and throw ERR_INVALID_STATE from the affected
entry points while it is on the stack. Covering every authorizer
invocation, including the re-prepare that SQLite can run during
sqlite3_step(), exposed a second and distinct hazard: reentering a
statement that is currently being stepped is a use-after-free rather
than a contract violation, since finalizing it frees the virtual machine
under sqlite3_step() and re-running it resets that machine
mid-execution. Any callback SQLite invokes during execution can reach
it, so a user-defined function is enough. Track the statements currently
being stepped and reject reentry into only those, which leaves a
user-defined function free to prepare, run, and finalize its own helper
statements.

Signed-off-by: Trevor Burnham <trevorburnham@gmail.com>
Fixes: nodejs#63207
Assisted-by: claude:opus-5
PR-URL: nodejs#65156
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Signed-off-by: Guilherme Araújo <arauujogui@gmail.com>
PR-URL: nodejs#62757
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Edy Silva <edigleyssonsilva@gmail.com>
Replace the async generator backing Symbol.asyncIterator with a
hand-rolled iterator. The generator machinery costs several extra
promise allocations and microtask hops per chunk: yield awaits the
yielded value and resolves the pending request through separate
promises. Buffered chunks are now delivered as an already-resolved
promise, one microtask sooner than before.

Thenable chunks are still awaited before delivery, requests received
while a next() is outstanding are queued, and return()/throw() before
the first next() complete the iterator without touching the stream.

The earlier delivery is observable by code racing an abort against
the first chunk. The flatMap AbortSignal test relied on such a race;
it is reworked to abort deterministically while two mappers are in
flight, asserting the concurrency limit, in-flight cancellation and
rejection, without depending on delivery timing or timers.

streams/readable-async-iterator.js sync='yes': +32.59% (***)
streams/readable-async-iterator.js sync='no': +9.84% (***)

Assisted-by: Claude Fable 5
Signed-off-by: Matteo Collina <matteo.collina@gmail.com>
PR-URL: nodejs#64447
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Mattias Buelens <mattias@buelens.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
The highWaterMark values were passed as properties of the underlying
source and sink dictionaries, where they are ignored: a queuing
strategy's highWaterMark is read from the constructors' second argument.
Every configuration therefore measured the identical workload at the
default highWaterMark of 1, which also explains the historically high
run-to-run variance of this benchmark family.

Pass the strategies as the constructors' second argument and cover the
default (1) alongside buffered (1024, 4096) configurations.

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: nodejs#65138
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Three related reductions on the per-chunk paths:

Wrap user sink.write and source.pull callbacks without coercing their
result into a promise. When the callback returns a non-thenable (the
common synchronous case), fulfillment is guaranteed and no then() lookup
is observable, so the fulfilled reaction is enqueued through a single
shared resolved promise at the exact microtask position the coerced
promise's reaction would have had, skipping the implicit async-wrapper
promise per chunk. Thenable results go through PromiseResolve(), which
matches the spec's "a promise resolved with" conversion (identity for
native promises).

Park pipeTo's pump on backpressure by installing a record that
duck-types the writer's lazily-materialized [[readyPromise]] record and
whose resolve function is the pump continuation itself. Backpressure
clearing then resumes the pump directly instead of materializing a fresh
promise record plus reaction per flip, and the pump no longer schedules
a microtask per batch. writableStreamUpdateBackpressure publishes the
new backpressure state before resolving the ready record so the pump
observes the updated value.

Replace queueMicrotask() on the pipeTo and tee chunk-forwarding paths
with a reaction on the shared resolved promise, which enqueues the
continuation at the same position without the per-call scheduling
overhead.

pipe-to improves by 8-14% across all benchmark configurations, with
readable-read and tee also improving in spot runs.

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: nodejs#65138
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
The start, pull, and write non-op algorithms are all raw callbacks with
an identical empty body now, so a single shared nonOpCallback replaces
nonOpStart, nonOpPull, and nonOpWrite.

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: nodejs#65138
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Signed-off-by: greenhead <shren0812@gmail.com>
PR-URL: nodejs#65265
Refs: https://www.sqlite.org/session/c_changeset_abort.html
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
The pointer range test creates multiple closures from the same function
literals and explicitly requests synchronous optimization. V8 can also
schedule concurrent recompilation for those closures.

Wait for background optimization before closing the dynamic library so
compiler jobs cannot outlive the fast FFI metadata they reference.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: codex:gpt-5.6-sol
PR-URL: nodejs#65300
Refs: https://github.com/nodejs/reliability/issues?q=sort%3Aupdated-desc%20%22test-ffi-fast-integer-validation%22
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
The quic implementation calls setWakeUp with
the assumption, that it is only executed once
per event loop cycle.
This assumption is wrong.
Only setImmediate will guarantee, that the
execution is delayed to later in the event loop
and happening once in the event loop.

Fixes: nodejs#64035
Signed-off-by: Marten Richter <marten.richter@freenet.de>
PR-URL: nodejs#64044
Reviewed-By: James M Snell <jasnell@gmail.com>
Signed-off-by: Felix P. <devfep@gmail.com>
PR-URL: nodejs#65268
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Signed-off-by: Guilherme Araújo <arauujogui@gmail.com>
PR-URL: nodejs#62241
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Co-authored-by: Aviv Keller <me@aviv.sh>
Signed-off-by: Aviv Keller <me@aviv.sh>
PR-URL: nodejs#64894
Fixes: nodejs#43583
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matthew Aitken <maitken033380023@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
To hopefully get to the bottom of WPT crashes that have no traces.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Co-authored-by: Aviv Keller <me@aviv.sh>
Signed-off-by: Aviv Keller <me@aviv.sh>
PR-URL: nodejs#64894
Fixes: nodejs#43583
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matthew Aitken <maitken033380023@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Signed-off-by: Aviv Keller <me@aviv.sh>
PR-URL: nodejs#64894
Fixes: nodejs#43583
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matthew Aitken <maitken033380023@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Co-authored-by: Aviv Keller <me@aviv.sh>
Signed-off-by: Aviv Keller <me@aviv.sh>
PR-URL: nodejs#64894
Fixes: nodejs#43583
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matthew Aitken <maitken033380023@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Signed-off-by: Aviv Keller <me@aviv.sh>
PR-URL: nodejs#64894
Fixes: nodejs#43583
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matthew Aitken <maitken033380023@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Signed-off-by: NIxxy25 <tellaoyinkansola25@gmail.com>
PR-URL: nodejs#65271
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Signed-off-by: Aviv Keller <me@aviv.sh>
PR-URL: nodejs#64986
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Replace `Array.prototype.forEach()` with `for...of` loops across 17
tests in `test/parallel`, so each loop body reads as a plain statement
rather than an arrow callback.

None of the iterated values are sparse arrays, the one case where
`forEach` and `for...of` genuinely differ, so both constructs visit the
same elements in the same order. No callback relied on `this`, an early
return, or async behaviour, and the number of assertions run in each
file is unchanged.

Signed-off-by: Phillip Markert <phillip@ephisys.com>
PR-URL: nodejs#65272
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Signed-off-by: freida-code <150387862+freida-code@users.noreply.github.com>
PR-URL: nodejs#65270
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
PR-URL: nodejs#65224
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Signed-off-by: Lazizbek Ergashev <lazerg2@gmail.com>
PR-URL: nodejs#65283
Fixes: nodejs#65280
Refs: nodejs/node-v0.x-archive#853
Refs: nodejs@3935adc
Refs: nodejs#18297
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
the binary-upload target uses $(TARNAME)-$(OSTYPE)-$(ARCH).tar.xz as the
name to upload whereas it is created by the $(BINARYTAR) target as
$(BINARYNAME). Since BINARYNAME includes the optional VARIATION when
present this gets missed out int he binary-upload target, for example
during a release build for Alpine/musl. This commit changes the
binary-upload target to use the same variable for the tarball that is
used when the file is created.

Signed-off-by: Stewart X Addison <sxa@ibm.com>
PR-URL: nodejs#65282
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Signed-off-by: 서울민트초코 <minseong130502@gmail.com>
PR-URL: nodejs#65295
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Signed-off-by: greenhead <shren0812@gmail.com>
PR-URL: nodejs#65274
Refs: nodejs#55266
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
The error thrown for a non-number min is unchanged.

Signed-off-by: greenhead <shren0812@gmail.com>
PR-URL: nodejs#65014
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
greenheadHQ and others added 18 commits August 17, 2026 03:39
The kValidateObjectAllowArray flag matches the replaced check: arrays
keep passing and the thrown error is unchanged.

Signed-off-by: greenhead <shren0812@gmail.com>
PR-URL: nodejs#65015
Reviewed-By: James M Snell <jasnell@gmail.com>
Use the standard SQLite integer conversion for changes and
lastInsertRowid. Throw ERR_OUT_OF_RANGE when a value cannot be
represented safely as a Number, or return it as a BigInt when
BigInt reads are enabled.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: codex:gpt-5.6-sol
PR-URL: nodejs#65178
Fixes: nodejs#65177
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Validate Broadcast.push() and Share.pull() signals before registering
raw consumers. Return a rejecting iterable for pre-aborted signals
without adding a cursor.

This prevents failed subscriptions from leaving unreachable cursors
that inflate consumerCount and can permanently impose backpressure.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: codex:gpt-5.6-sol
PR-URL: nodejs#65299
Fixes: nodejs#65298
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jason Zhang <xzha4350@gmail.com>
Add a WatchdogBinding declaration for internalBinding('watchdog')
and wire it into InternalBindingMap.

Signed-off-by: leah-1ee <selee3196@gmail.com>
PR-URL: nodejs#65228
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Add a DiagnosticsChannelBinding declaration for
internalBinding('diagnostics_channel') and wire it into
InternalBindingMap.

Signed-off-by: leah-1ee <selee3196@gmail.com>
PR-URL: nodejs#65227
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
The inspector can accept a connection before an --inspect-brk target
enters its frontend wait. Runtime.runIfWaitingForDebugger can then be
handled too early, allowing the target to subsequently block forever.

Wait for NodeRuntime.waitingForDebugger before initializing and
releasing launched targets. Race the handshake against disconnects and
apply it to both interactive and probe startup.

Refs: nodejs#64116
Assisted-by: codex:gpt-5.6-sol
Co-authored-by: Archkon <180910180+Archkon@users.noreply.github.com>
Signed-off-by: Archkon <180910180+Archkon@users.noreply.github.com>
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: nodejs#65194
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Add a SignalWrapBinding declaration for internalBinding('signal_wrap')
and wire it into InternalBindingMap.

Signed-off-by: leah-1ee <selee3196@gmail.com>
PR-URL: nodejs#65229
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
PR-URL: nodejs#61198
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Jordan Harband <ljharb@gmail.com>
Signed-off-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#65198
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Use concise method functions for Fast API and shared-buffer wrappers,
and create native fallback functions with ConstructorBehavior::kThrow,
so FFI functions remain non-constructible on all invocation paths.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: codex:gpt-5.6-sol
PR-URL: nodejs#65184
Fixes: nodejs#65183
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
InvokeCallback tested `args[i] == nullptr` and mapped the argument to
JS `null`. `args` is libffi's avalue array, and libffi always points
each slot at its own storage for the corresponding argument, so the
slot pointers are never null and the branch never ran.

The check also read as a guarantee the code does not provide: a NULL
pointer argument surfaces as the BigInt `0n`, because ToJSArgument
converts `ffi_type_pointer` values with BigInt::NewFromUnsigned. Drop
the branch rather than reimplementing it in ToJSArgument, which would
change behavior by making pointer parameters arrive as either a BigInt
or `null`.

Signed-off-by: Trivikram Kamat <16024985+trivikr@users.noreply.github.com>
Assisted-by: claude:opus-5
PR-URL: nodejs#64998
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Signed-off-by: avivkeller <me@aviv.sh>
PR-URL: nodejs#64590
Reviewed-By: James M Snell <jasnell@gmail.com>
Long-term itch. Per v8 rules, we're not supposed to be
heap allocating v8::Local's; instead we're supposed to
be using v8::LocalVector. Create a specialization of
MaybeStackBuffer that uses either a stack array of
v8::Locals or v8::LocalVector with some additional
utility improvements.

Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#65159
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
`maybeEnableKeylog()` runs as the agent's `'newListener'` handler and
attaches the agent's keylog handler to the sockets the agent already
owns. `agent.sockets` maps a name to an array of sockets, but the loop
treated those arrays as sockets and called `.on()` on them.

Adding a `'keylog'` listener to an agent that already owned a socket
therefore threw `TypeError: sockets[i].on is not a function` out of
`agent.on('keylog', ...)`. Since the throw happened inside the
`'newListener'` handler it propagated before the listener was stored,
so the caller got an exception and no listener. Sockets parked in
`agent.freeSockets` were never visited at all.

Walk both maps the way `Agent.prototype.destroy()` does.

Signed-off-by: Shani Singh <teamdeveloperworld@gmail.com>
PR-URL: nodejs#65066
Reviewed-By: Tim Perry <pimterry@gmail.com>
Fixes: nodejs#64214
Signed-off-by: y1d7ng <y1d7ng@yeah.net>
PR-URL: nodejs#64227
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Claudio Wunder <cwunder@gnome.org>
Signed-off-by: ulofiai <monsterking@tutamail.com>
PR-URL: nodejs#65095
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Stefan Stojanovic <stefan.stojanovic@janeasystems.com>
An expired timer can run before the first complete event loop
iteration, disabling the histogram before it records any samples.

Drive a known number of iterations with setImmediate before checking
the histograms, and share the chain between resolution variants.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: codex:gpt-5.6-sol
PR-URL: nodejs#64728
Refs: https://github.com/nodejs/reliability/issues?q=sort%3Aupdated-desc%20test-performance-eventloopdelay
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
PR-URL: nodejs#65317
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
@cursor
cursor Bot force-pushed the cursor/url-parse-performance-603e branch 3 times, most recently from a66b5bc to 39c4db7 Compare August 18, 2026 12:49
Parse one-byte ASCII inputs in place instead of copying them into a
UTF-8 buffer, and reuse the original V8 string when the serialized
href is unchanged. Delay URLContext allocation until parse finishes
and skip ToString when the input is already a string.

Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
@cursor
cursor Bot force-pushed the cursor/url-parse-performance-603e branch from 39c4db7 to fa5ca3f Compare August 18, 2026 12:50
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.