Conversation
|
Before doing a "campaign" of slop, please do the bare minimum of asking the maintainers. None of us want to spend time reviewing these. |
|
Sorry, I just wanted to help out by trying to find small things that can be improved. These are single file/line changes that measurably improve the performance, even though just minimally. But what's the "slop" in there? |
|
@zirkelc ... your motivation is fine, to be honest, and using an AI agent to help is generally perfectly acceptable. The change here also is well motivated and should be considered. The regex approach is definitely way faster than the naive linear scan. That said, I think we could do better and, long term, there's no reason why we can't rely on the runtime to help us make this even faster. nodejs/node#66298 @mcollina ... I think it's likely worth re-opening this. |
|
I would honestly prefer to disable outside contributors entirely... people can still open issues. We all have access to ai here and therefore all of us can open, at worst, an equally acceptable PR. There is a difference between having ai autonomously spam open PRs and actual contributors using ai to contribute. I am not debating the validity of this PR (out of 4), I am against the methodology of spamming PRs (where at LEAST half of them are invalid) in the hopes some land. |
|
For this particular change, the regex approach is faster in every case. For smaller values only marginally but it scales way better as strings get larger and more complex. I'd say this change is worth taking but we might also wait until nodejs/node#66298 lands and is available (and backported) to releases. Obviously we won't be able to rely on it entirely but a builtin + regex approach will be faster than this linear scan. |
|
Yes, I'm not debating the validity of this one change (out of four rapid-fire low effort PRs), but the methodology by the author. Throwing things at the wall and hoping something sticks isn't an acceptable way to contribute to opensource, nor do I find it polite to ask maintainers to do the due diligence you yourself have not done. For every invalid PR, it also takes far more time to refute and review than it does for them to ask [ai agent] to open a PR (Brandolini's law, but applied to opensource). |
This relates to...
webidl.converters.ByteStringruns for every header name and value that passes through the public header API:new Headers(init),append,set,get,has,delete,RequestInit.headers,ResponseInit.headers.Rationale
The step "if any element of x is greater than 255, throw" ran as a JavaScript loop over every code unit. Measured in isolation, that loop was half the cost of converting a header record. A regular expression test for a code unit in
\u0100-\uffffdoes the same check natively, about 3x faster on realistic header names and values. Only when it matches doessearch()find the index for the unchanged error message. Without theuflag the pattern matches single UTF-16 code units, so lone surrogates still fail, exactly like the loop.(
test()thensearch()rather thansearch()alone, becausesearch()was about 30% slower thantest()on the success path.)Changes
lib/web/webidl/index.js: the check above.Features
N/A
Bug Fixes
N/A
Breaking Changes and Deprecations
N/A
Verification (this branch vs
328ab843)Headline numbers are standalone: one revision per process, 8 alternating process pairs, minimum of 100 runs per process, with an identical-code control (base against base) run the same way.
new Headers(record)+ readsgetCookies/getSetCookies/setCookieThe paired runs this branch was verified with (they decide experiments, they do not set the claim):
Observable surface
TypeErrortext is identical (the guard hashes it, and a differential run over 30 000 generated records with characters above 255 and surrogate pairs is identical).Invariants this relies on
goryflag, sotest()andsearch()keep no state between calls.Open questions for maintainers (not in this PR)
__proto__in a record is silently dropped:new Headers(JSON.parse('{"__proto__":"x"}'))has no entries, because the record converter assigns keys on a plain{}. Browsers keep the header. Fixing it changes behaviour, so it is not part of this PR.WPT (
npm run test:wpt: /fetch, /mimesniff, /xhr, /websockets, /eventsource) was run locally on328ab843and on this branch: per test and per case, pass/fail is identical across all 1 282 test files.Note on CI:
Test with Node.js 22 compiled --without-intlalready fails onmainat328ab843, before this change.Reproducing the numbers
The harness (A/B runner, guard, differential, focused and standalone runners) lives in
perf/on the campaign branch: zirkelc/undici@afde9423/perf (the plan and the experiment log with all discarded experiments are in the same directory). It needs Node 24 (it runs.mtsdirectly) and no install beyondnpm ci.A row marked
?has an interquartile band that crosses zero in that run; judge by two runs that agree, and by the standalone numbers.perf/cases.mts, the workloads these numbers come fromStatus
Companion PRs from the same campaign: #5901 (perf(fetch): avoid redundant request state in the Request constructor), #5902 (perf(websocket): mask frames without a mask array, four bytes per step), #5904 (perf(cookies): split each cookie pair once in getCookies)