Why is iterating through an array backwards faster than forwards
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.
Comments
-
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 over 12 yearslook at the hard coded test jsperf.com/array-iteration-direction ... using your logic it should be faster no?
-
samccone over 12 yearsAhhh... interesting your method now takes the crown for fastest iteration jsperf.com/array-iteration-direction
-
Mike Dunlavey over 12 yearsThe backward case isn't right. What I do is
for(i=len; --i>=0;){
-
Mike Dunlavey over 12 yearsIt should be
while(--L>=0) arr[L] = L;
-
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 over 12 yearsYep, 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 over 12 yearsalright you are correct... it looks like it is really a mixed bag of results tho but caching does help it... thanks XD
-
ajax333221 almost 12 yearsyou can even do
for(... ; i-- ;)
-
Breno Inojosa about 10 yearsso 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 about 10 yearsafaik,
i<l
is a different computation thani>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 over 9 yearsThe 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 over 9 years@bryc: So what? Of course it needs to be. Did I say something else?
-
Max Yari about 9 yearsIsnt this loop
for (var i = arr.length; i-- > 0; )
going to miss 0 index as 1-- !>0? maybe this one needs to befor (var i = arr.length; i-- >= 0; )
-
Bergi about 9 years@MaxYari: No. The
i
in the loop body (after being decremented) is always one smaller than thei
seen in the condition (before being decremented). What you would need isfor (var i=arr.length-1; i>=0; --i)
-
Max Yari about 9 yearstested, 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 about 9 years@MaxYari: Read on prefix/postfix decrement operators then
-
Max Yari about 9 yearsOh snap!! you opened my eyes, what a shame, thank you)
-
Gaurang Patel over 6 yearsFast 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 about 5 years
for (let i = arr.length; i-- > 0;) {