lib: reuse default DOMException in AbortController#47908
lib: reuse default DOMException in AbortController#47908debadree25 wants to merge 2 commits intonodejs:mainfrom
Conversation
| if (reason === undefined) { | ||
| reason = lazyDOMException(); | ||
| } |
There was a problem hiding this comment.
Would reason ??= lazyDOMException(); also work in here, and in the next usage?
There was a problem hiding this comment.
I think so yes! updating this (since benchmark ci is running would pushing a commit interfere with it?)
There was a problem hiding this comment.
No, it won't interfere with it. 👍
There was a problem hiding this comment.
I don’t think this is correct, users should be able to supply null as a reason
| abort(reason = new DOMException('This operation was aborted', 'AbortError')) { | ||
| abort(reason) { | ||
| if (reason === undefined) { | ||
| reason = lazyDOMException(); |
There was a problem hiding this comment.
Since we are not creating a new error everytime abort is called, 2 different usages in the code throwing this error, might have a different stack trace. Is this compliant with the spec?
There was a problem hiding this comment.
ah good point, not sure about that, one thing we could do maybe is move this lazy loading inside the functions themselves. that should ensure correct trace?
lib/internal/abort_controller.js
Outdated
| static abort( | ||
| reason = new DOMException('This operation was aborted', 'AbortError')) { | ||
| static abort(reason) { | ||
| reason ??= lazyDOMException(); |
There was a problem hiding this comment.
I think this won’t let users define a null abort reason. Any reason to use this syntax over what was before? Also it changes the .length property of the static method from 0 to 1
There was a problem hiding this comment.
.length property? didn't get you
There was a problem hiding this comment.
The function's .length property (controller.abort.length) which is typically not important but in web standards like AbortController it is
There was a problem hiding this comment.
Ah ok got it, it expects the reason param now thats why
d2923f0 to
832efd8
Compare
benjamingr
left a comment
There was a problem hiding this comment.
Good work but as others mentioned this means that all the aborts get the same stack trace and it's impossible to figure out where an error came from so the performance benefit is probably not worth the debugging downside of knowing who called ".abort" which is currently possible since the error is captured in .abort but now becomes impossible IIUC.
|
(I have no idea just asking) is there maybe a way to recapture the trace and inject the details into the lazy loaded one? |
|
I think something like Error.captureStackTrace could help? or would it just erase the gains. |
|
I'm afraid creating the error and capturing the stack is the expensive part so I'm not sure, it may be worth while to optimize DOMException itself |
|
It may be fast to not create the DOMException in |
|
IIUC it is for reason only |
|
Hey so in 5259cbe I did the following
'use strict';
const ac1 = new AbortController();
ac1.signal.addEventListener('abort', () => {
console.log(ac1.signal.reason);
});
const ac2 = new AbortController();
ac2.signal.addEventListener('abort', () => {
console.log(ac2.signal.reason);
});
function abortThis(controller) {
controller.abort();
}
function abortThis2(controller) {
controller.abort();
}
setTimeout(() => {
abortThis(ac1);
setTimeout(() => {
abortThis2(ac2);
}, 100);
}, 100);On normal node trace looks like this DOMException [AbortError]: This operation was aborted
at new DOMException (node:internal/per_context/domexception:53:5)
at AbortController.abort (node:internal/abort_controller:331:18)
at abortThis (/Users/debadreechatterjee/Documents/Personal/node/test.js:11:14)
at Timeout._onTimeout (/Users/debadreechatterjee/Documents/Personal/node/test.js:17:3)
at listOnTimeout (node:internal/timers:573:17)
at process.processTimers (node:internal/timers:514:7)
DOMException [AbortError]: This operation was aborted
at new DOMException (node:internal/per_context/domexception:53:5)
at AbortController.abort (node:internal/abort_controller:331:18)
at abortThis2 (/Users/debadreechatterjee/Documents/Personal/node/test.js:14:14)
at Timeout._onTimeout (/Users/debadreechatterjee/Documents/Personal/node/test.js:19:5)
at listOnTimeout (node:internal/timers:573:17)
at process.processTimers (node:internal/timers:514:7)On this PR DOMException [AbortError]: This operation was aborted
at AbortController.abort (node:internal/abort_controller:352:7)
at abortThis (/Users/debadreechatterjee/Documents/Personal/node/test.js:11:14)
at Timeout._onTimeout (/Users/debadreechatterjee/Documents/Personal/node/test.js:17:3)
at listOnTimeout (node:internal/timers:573:17)
at process.processTimers (node:internal/timers:514:7)
DOMException [AbortError]: This operation was aborted
at AbortController.abort (node:internal/abort_controller:352:7)
at abortThis2 (/Users/debadreechatterjee/Documents/Personal/node/test.js:14:14)
at Timeout._onTimeout (/Users/debadreechatterjee/Documents/Personal/node/test.js:19:5)
at listOnTimeout (node:internal/timers:573:17)
at process.processTimers (node:internal/timers:514:7)and the performance benefit still seems to exist, although not as impressive as the initial one: confidence improvement accuracy (*) (**) (***)
events/abortcontroller-abort.js n=1000000 *** 20.64 % ±3.77% ±5.01% ±6.53%
Be aware that when doing many comparisons the risk of a false-positive result increases.
In this case, there are 1 comparisons, you can thus expect the following amount of false-positive results:
0.05 false positives, when considering a 5% risk acceptance (*, **, ***),
0.01 false positives, when considering a 1% risk acceptance (**, ***),
0.00 false positives, when considering a 0.1% risk acceptance (***)wdyt @benjamingr |
|
Wouldn't that replace the stack trace on earlier references to the error "under the hood" since it's the same reference? |
|
Ah oh no yes, I am not thinking straight 😓😓 I guess then this a dead end 😕 |
|
Probably no other way, for now, maybe we could optimize DOMException, I am closing this for now, If there are any other ideas I think we can discuss on this PR thread |
Similar to #46086 have reused the default DOMException we throw when calling
ac.abort(), so far the tests dont break and the benchmark added in this PR show good improvementBenchmark results:
Refs: #46086
Refs: nodejs/performance#44