Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
871 views
in Technique[技术] by (71.8m points)

performance - javascript 'let' and 'var' in for-loops

On my search for concrete numbers to back usage of the const keyword in Javascript, I stumbled upon a performance comparision between all three variable declaration types var, let and const. I didn't like the test setup, so I created a simplified one.

I didn't expect much difference and Firefox measured up to my expectations:

jsPerf results on Firefox 52

But in Chromium something weird happened:

jsPerf results on Chrome 57

Not only are all test results significantly lower but let inside the loop breaks down to a fraction of the speed.

I decided to run the tests in Browserstack to make sure it is not my quirky Linux setup. The same happens there with Firefox 53 and Chrome 58 on Windows 10. I even tested the somewhat older Chrome 50 and got the same behaviour.

What is going on? Is it a bug?

EDIT: Some commented that the loop is probably just optimized away as it is doing nothing. To show, that this is not the case, I changed the test.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When you use let the body of the for loop must create a new scope to handle the correct lifetime for the loop variable, however in many cases it is possible to optimise away the extra code and runtime. For example consider this code:

let sum = 0;
let fns = [];
for (let i=0; i < 1000; i++) {
  function foo() { sum += i; }

  fns.push(foo);

}

When you run it through babeljs you can see the equivalent ES5 code it produces includes a function call in order to preserve the correct variable lifetimes:

var sum = 0;
var fns = [];

var _loop = function _loop(i) {
  function foo() {
    sum += i;
  }

  fns.push(foo);
};

for (var i = 0; i < 1000; i++) {
  _loop(i);
}

However, babel is intelligent enough that if you don't do anything which requires extending the lifetime of the loop variable it simply uses an ordinary for loop with the body inline. So your code:

for (let i=0; i < 1000; i++) {
  true;
}

can be shown to be exactly equivalent to:

for (var i=0; i < 1000; i++) {
  true;
}

My guess would be that something very similar happens internally in Chrome, but they haven't yet optimised out the cases where they don't have to keep the loop variable alive.

It would be interesting to see how the code I used at the top of this example compares in Firefox and Chrome as I suspect they should both end up similarly slow. You should beware of timing things like empty loops as the results can be skewed by optimisation far more than is normal for actual code.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...