Performance concern with let/const
Andreas Rossberg
rossberg at google.com
Mon Sep 17 03:47:07 PDT 2012
On 17 September 2012 03:35, Luke Hoban <lukeh at microsoft.com> wrote:
> __Temporal dead zones__
>
> For reference on previous discussion of temporal dead zone see [1].
>
> I've expressed concerns with the performance overhead required for temporal dead zones in the past, but we did not at the time have any data to point to regarding the scale of the concern.
>
> As an experiment, I took the early-boyer test from V8 and changed 'var' to 'let'. In Chrome preview builds with 'let' support, I saw a consistent ~27% slowdown. That is, the 'let is the new var' mantra leads to 27% slower code in this example for the same functionality.
Just to be clear, the V8 implementation of block scoping and 'let' has
not seen any serious performance optimisation yet. So I'd take these
numbers (which I haven't verified) with a large grain of salt.
Also, I conjecture that the main cost for 'let' isn't the temporal
dead-zone, but block allocation. In particular, a 'let' in a loop
costs a significant extra if no static analysis is performed that
would allow hoisting the allocation out of the loop.
> However, we are aware that there are a class of dynamic checks that can be removed by static analysis - in particular intra-procedural use before assignment checks. We implemented these checks in a Chakra prototype, and even with these, we still see an ~5% slowdown.
I would like to understand this better. AFAICT, you don't necessarily
need much static analysis. In most cases (accesses from within the
same closure) the check can be trivially omitted. In addition, once
you optimise based on type feedback it is also trivial to discover
that the check is no longer needed in other situations. I would expect
those scenarios to cover most performance-relevant programming
patterns quite well.
> __ Early Errors__
>
> Let and const introduce a few new early errors (though this general concern impacts several other areas of ES6 as well). Of particular note, assignment to const and re-declaration of 'let' are spec'd as early errors.
>
> Assignment to const is meaningfully different than previous early errors, because detecting it requires binding references *before any code runs*. Chakra today parses the whole script input to report syntax errors, but avoids building and storing ASTs until function bodies are executed [2]. Since it is common for significant amounts of script on typical pages to be downloaded but not ever executed, this can save significant load time performance cost.
>
> However, if scope chains and variable reference binding for all scopes in the file need to be established before any code executes, significantly more work is required during this load period. This work cannot be deferred (and potentially avoided entirely if the code is not called), because early errors must be identified before any code executes.
>
> This ultimately means that any script which mentions 'const' will defeat a significant aspect of deferred AST building, and therefore take a load time perf hit.
This is indeed a concern. However, I don't think 'const' is the only
problem, other ES6 features (such as modules) will probably introduce
similar classes of early errors.
> More generally - this raises a concern about putting increasingly more aggressive static analysis in early errors. It may, for example, argue for a 3rd error category, of errors that must be reported before any code in their function body executes.
I agree that this is a worthwhile possibility to consider. I mentioned
this idea to Dave once and he didn't like it much, but maybe we should
have a discussion.
/Andreas
More information about the es-discuss
mailing list