Why is iterating through an array backwards faster than forwards

52,528

Solution 1

Because your forwards-condition has to receive the length property of your array each time, whilst the other condition only has to check for "greater then zero", a very fast task.

When your array length doesn't change during the loop, and you really look at ns-perfomance, you can use

for (var i=0, l=arr.length; i<l; i++)

BTW: Instead of for (var i = arr.length; i > 0; --i) you might use for (var i = arr.length; i-- > 0; ) which really runs through your array from n-1 to 0, not from n to 1.

Solution 2

Because in the first form you are accessing the property length of the array arr once for every iteration, whereas in the second you only do it once.

Solution 3

If you want to have them at same pace, you can do that for forward iteration;

for(var i=0, c=arr.length; i<c; i++){
}

So, your script won't need to take length of array on everystep.

Solution 4

I am not entirely sure about this, but here is my guess:

For the following code:

for (var i = 0; i < arr.length; ++i) {;
}

During runtime, there is an arr.length calculation after each loop pass. This may be a trivial operation when it stands alone, but may have an impact when it comes to multiple/huge arrays. Can you try the following:

 var numItems = arr.length;
    for(var i=0; i< numItems; ++i)
    {
    }

In the above code, we compute the array length just once, and operate with that computed number, rather than performing the length computation over and over again.

Again, just putting my thoughts out here. Interesting observation indeed!

Solution 5

i > 0 is faster than i < arr.length and is occurring on each iteration of the loop.

You can mitigate the difference with this:

for (var i = 0, len = arr.length; i < len; ++i) {;
}

This is still not as fast as the backwards item, but faster than your forward option.

Share:
52,528
samccone
Author by

samccone

Figuring it out as I go

Updated on July 08, 2022

Comments

  • samccone
    samccone almost 2 years

    Given this code:

    var arr = [];
    
    for (var i = 0; i < 10000; ++i)
        arr.push(1);
    

    Forwards

    for (var i = 0; i < arr.length; ++i) {}
    

    Backwards

    for (var i = arr.length - 1; i >= 0; --i) {}
    

    Hard-coded Forward

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

    Why is backwards so much faster?

    Here is the test: http://jsperf.com/array-iteration-direction

  • samccone
    samccone over 12 years
    look at the hard coded test jsperf.com/array-iteration-direction ... using your logic it should be faster no?
  • samccone
    samccone over 12 years
    Ahhh... interesting your method now takes the crown for fastest iteration jsperf.com/array-iteration-direction
  • Mike Dunlavey
    Mike Dunlavey over 12 years
    The backward case isn't right. What I do is for(i=len; --i>=0;){
  • Mike Dunlavey
    Mike Dunlavey over 12 years
    It should be while(--L>=0) arr[L] = L;
  • jfriend00
    jfriend00 over 12 years
    @samccone - what result are you seeing (which test in which browser)? I'm seeing that caching the length is always at least as fast and usually faster.
  • Jeffrey Sweeney
    Jeffrey Sweeney over 12 years
    Yep, this is how I do it for optimized functions. Just note that if the array is mutable (and it usually isn't), this may skip a resource or two. For example, this won't work if you're looping through elements that the loop itself is adding or deleting.
  • samccone
    samccone over 12 years
    alright you are correct... it looks like it is really a mixed bag of results tho but caching does help it... thanks XD
  • ajax333221
    ajax333221 almost 12 years
    you can even do for(... ; i-- ;)
  • Breno Inojosa
    Breno Inojosa about 10 years
    so basically it means that if I don't change the array and I keep array.length in a variable, then backwards speed = forward speed? Example: var length = array.length; for(var i = 0 ; i<length ; i++);
  • Bergi
    Bergi about 10 years
    afaik, i<l is a different computation than i>0, but yes they're rather equal (faster than uncached length): jsperf.com/array-iteration-direction/3 - yet some engines do recognize and optimize some of these cases
  • bryc
    bryc over 9 years
    The condition of a loop is evaluated on each iteration. Think of it like var i = 0; var a = i < 10; while(a) { i++; a = i < 10; }.
  • Bergi
    Bergi over 9 years
    @bryc: So what? Of course it needs to be. Did I say something else?
  • Max Yari
    Max Yari about 9 years
    Isnt this loop for (var i = arr.length; i-- > 0; ) going to miss 0 index as 1-- !>0? maybe this one needs to be for (var i = arr.length; i-- >= 0; )
  • Bergi
    Bergi about 9 years
    @MaxYari: No. The i in the loop body (after being decremented) is always one smaller than the i seen in the condition (before being decremented). What you would need is for (var i=arr.length-1; i>=0; --i)
  • Max Yari
    Max Yari about 9 years
    tested, yes 0 is here, i honestly did not understand yet why, isnt it in the first place decrements i, then compares to 0, then decides to run iteration or not. Like this, it seems that 1 must be decremented to 0, therefore not starting iteration as it's not > 0
  • Bergi
    Bergi about 9 years
    @MaxYari: Read on prefix/postfix decrement operators then
  • Max Yari
    Max Yari about 9 years
    Oh snap!! you opened my eyes, what a shame, thank you)
  • Gaurang Patel
    Gaurang Patel over 6 years
    Fast forward to 2018. it looks like the modern versions of browsers don't make loop slower even when accessing arr.length in each iteration (your forwards case)
  • Vincent
    Vincent about 5 years
    for (let i = arr.length; i-- > 0;) {