-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optional Chaining performance issue #37380
Comments
Babel's output seems to be roughly the same: var _options;
if (typeof ((_options = options) === null || _options === void 0 ? void 0 : _options.onCancel) === 'function') {
options.onCancel();
} Is there a way to transpile this with fully correct runtime behavior that's faster? Also, what's the slowdown in real world code, instead of one line microbenchmarks? |
The one I used originally is correct enough: if(options && typeof options.onCancel === 'function') {
options.onCancel();
} But for complete accuracy, you can add object verification: if(options && typeof options === 'object' && typeof options.onCancel === 'function') {
options.onCancel();
} Both perform significantly faster than what we are getting currently generated by TypeScript.
Well, I have this code used in a loop that runs 100,000 times, and the slow version of code kills the performance, so I had to stop using the optional chaining operator in TypeScript. |
Neither of those produces identical runtime behavior to the optional chaining scenario. This example prints 2, but if your transformation was valid it would print 1 2 3 var options = document.all
options.onCancel = function() { console.log("1") }
if(options && typeof options.onCancel === 'function') {
options.onCancel();
}
options.onCancel = function() { console.log("2") }
if(typeof options?.onCancel === 'function') {
options.onCancel();
}
options.onCancel = function() { console.log("3") }
if(options && typeof options === 'object' && typeof options.onCancel === 'function') {
options.onCancel();
} |
How did you test your own example? I am getting |
Use any actual web browser console. (Not sure what it will do in something like node+jsdom). |
@nmain So you are using this ancient abomination as a test, one that nobody cares about today anymore. I'm not sure how good of an argument this makes today. Even the official standard refers to it as ancient violation of the standard. And if TypeScript really needs to support it still, it can run a transpile-time check, to spot that break of rule and emit the longer check instead, while for everything else it can emit a much shorter and better-performing one, as shown before. |
How would you verify that some particular variable never assumes the value of |
Actually, it is much simpler than you might think. That rule violation only matters when emitting ES3 code. If the target is ES5 or later, then it is no longer relevant. And in my example, I use NodeJS + ES6 as target, so I would expect that ancient browser compatibility to be thrown away. |
All current browsers fully respect Another problem is that your suggested transformation isn't even a drop in replacment for Adding special emit rules like that for various combinations of compound expressions to the typescript compiler would be a huge burden. |
I cannot fathom who in his right mind would use But here's a well-performing version of the code: if (options !== null && options !== undefined && typeof options.onCancel === 'function') {
options.onCancel();
} I think it is the exact match to the original logic. |
@vitaly-t That is not an exact match to the original logic. |
ES2015 code generated for optional chaining shows horrible performance.
In my project, after I replaced this type of code:
with this one:
I got the following code generated by TypeScript for ES2015 target:
Somehow, performance of such code is dramatically worse than what I had before, like 10 times.
Expected behavior:
Comparable performance.
Actual behavior:
Horrific drop in performance. Chrome engine does not like that kind of code at all.
The text was updated successfully, but these errors were encountered: