Sean Anderson
Sean Anderson

Reputation: 29371

array.forEach running faster than native iteration? How?

http://jsperf.com/testing-foreach-vs-for-loop

It was my understanding that Test Case 2 should run more slowly than Test Case 1 -- I wanted to see how much more slowly. Imagine my surprise when I see it runs more quickly!

What's going on here? Behind the scenes optimizaiton? Or is .forEach cleaner AND faster?

Testing in Chrome 18.0.1025.142 32-bit on Windows Server 2008 R2 / 7 64-bit

Upvotes: 10

Views: 12531

Answers (5)

Erik  Reppen
Erik Reppen

Reputation: 4635

UPDATE:

A lot of the old tricks in these answers are great for interpreted JS in older browsers.

In any modern JS implementation including all modern browsers, Node, and the latest mobile webviews, inline functions can actually be cached by the JIT (JS compiler), making forEach a much faster option for array iteration, typically. It used to be the opposite where just making calls to a function repeatedly required a build-up/teardown process that could severely diminish performance of a non-trivial loop.

For best performance I'd avoid referencing anything that wasn't passed as an argument or defined inside the function itself if you don't have to. I'm not 100% sure that matters but I could see why it might.

Getter values that involve any kind of lookup process like array lengths or DOM node properties are probably also still best cached to a variable.

But beyond that I'd try to just let the basic principle of work avoidance guide your perf efforts. Pre-calculating things that don't need to be recalculated in a loop, or caching a query selector result to var rather than rummaging in the DOM repeatedly are good examples of this. Trying too hard to take advantage of JIT behavior is probably going to get pretty arcane and not likely to hold up over time or across all JITs.

OLD ANSWER:

Okay, forget wall of text. Bullet points:

var i = someArray.length; //length is cached
someArray.reverse(); //include this only if iterating in 0-(length-1) order is important

while(i--){
//run a test statement on someArray[i];
}
  • length is cached and immediately made into the index

  • The benefit of iterating backwards in JS AFAIK is avoiding a logical operator with two operands. In this case we're just evaluating a number. It's true or it's zero and false.

  • I also find it elegant.

Upvotes: 3

jbabey
jbabey

Reputation: 46657

There are many iteration optimizations that your for loop is missing such as:

  • cache the array length
  • iterate backwards
  • use ++counter instead of counter++

These are the ones that I have heard of and used, I am sure there are more. If memory serves me correct, the backwards iterating while loop is the fastest of all looping structures (in most browsers).

See this jsperf for some examples.

Edit: links for postfix vs prefix perf test and iterating backwards. I was not able to find my reference for using +=1 instead of ++, so I have removed it from the list.

Upvotes: 12

CoursesWeb
CoursesWeb

Reputation: 4237

Maybe the for() is slower because the loop applies 'array.length' to each iteration, to get the array's length.

Try:

var nri = array.length;
for( var i = 0; i < nri; i++ ){
   // ...
}

Upvotes: 0

kirilloid
kirilloid

Reputation: 14304

Reading length from array at each iteration may be slow, but forEach is comomonly slower, cause function call isn't cheap operation in js.

PS: forEach is 14% slower on FF10.

Upvotes: 1

Jordan
Jordan

Reputation: 32552

They're approximately the same for me in Opera. Something to note is that your conditional in the for() is array.length. If you cache the length of the array in a variable, and then loop, you should see better performance.

Upvotes: 0

Related Questions