Hacker News new | ask | show | jobs
by SerpentJoe 3776 days ago
I wonder which features are slow. I'm assuming generators and by extension the for-of syntax, which is otherwise a thing of beauty. I imagine proxies are somewhere between slow and horrifyingly slow.

I have noticed that none of the features I'd hoped would save cycles (const, generators, fat arrow functions) seem to be helping at all in the browsers of today.

3 comments

When last I checked, V8 simply triggers a deopt when it encounters any ES6 syntax at all - so just putting an unused "let foo;" in a function will kill its performance, regardless of whether any ES6 features are used.

Of course, it may be that some ES6 features will still be slow even after they've been optimized for, but right now, as a practical matter, I think ES6 is slow simply because the engines don't yet optimize it.

Last time I checked, fat arrow functions have a performance penalty because of all the optimisations that's made around scope in regular ES5 functions can't be used.

I believe ES6 fat arrow functions are slow for a similar reasons as why regular functions are slow when you use the magic arguments variable.

Regarding the scope optimizations: that's an interesting point. I wonder if the different scoping of let/const also create a performance penalty versus var.
This is true as well.
I wouldn't be surprised if const and arrow functions actually make things slower. const, or at least a naive implementation of it, requires checking if the value is changed which var does not. Perhaps that could be equally performant in time.

Arrow functions seem like they would take (marginally) longer to parse than explicit function declarations due to having a more verbose AST that does not start with unambiguous tokens. That, and you have the implicit this binding which must come with a cost. Again, in time this might be okay.

Wouldn't const be checked at compile time?
That's still a check that var is not subject to. Hence, it's a little slower (in theory).
In theory, the opposite, because a compiler knows that a constant binding never changes so the value it references can be inlined everywhere it is used without having to do runtime checks. But I think engines are not doing this yet.
I haven't written enough ES6 to answer this for myself, but doesn't the dynamic nature of the language mean that constants can be at risk of invalid LHS operations at run-time? (At least, those positioned high enough in the scope to be subject to the necessary operations, which could be a lot.) I'm thinking of eval specifically, but perhaps there are other ways of doing this.
I think if you use eval, all bets are off anyway.

But I think that in ES6 without eval you can't refer to the current scope in a dynamic way; which means that the engine can resolve bindings at compile time without worrying about people fiddling with scopes behind the scenes, which should simplify optimisation a lot.