Performance concern with let/const

Luke Hoban lukeh at
Mon Sep 17 08:05:58 PDT 2012

From: Andreas Rossberg [mailto:rossberg at] 
> On 17 September 2012 03:35, Luke Hoban <lukeh at> wrote:
> > __Temporal dead zones__
> >
> > 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.

Yes - sorry I didn't make this more clear.  This baseline was relevant mostly because it motivated trying to gather data with some of the key optimizations implemented.

> 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.

That may well be another significant perf concern.  For early-boyer in particular, I believe the structure of the code ensures that this particular issue will not come into play - the code largely hoists variable declarations to top of function scope.  

> > 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. 

Yes - this is what we implemented in the Chakra prototype.  Though note that the 'switch' issue raised on the list recently leads to cases even within a closure body where static analysis is insufficient - such as this (though I would guess this case won't be the primary perf culprit):

function(x) {
   do {
        switch(x) {
            case 0:
                return x;    //always a runtime error
            case 1:
                let x;
                x = 'let';     //never a runtime error
            case 2:
                return x;    //sometimes a runtime error
    } while (foo());

>> __ Early Errors__
>> 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.

Agreed - this concern is broader 'let'/'const'.

>> 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.

I understand the potential concern with this sort of thing - it weakens the upfront feedback from early errors.  But I'm not sure JavaScript developers really want to pay runtime performance cost in return for more up front static analysis during page load.


More information about the es-discuss mailing list