JavaScript loop performance - Why is to decrement the iterator toward 0 faster than incrementing

I'm not sure about Javascript, and under modern compilers it probably doesn't matter, but in the "olden days" this code:

for (i = 0; i < n; i++){
  .. body..
}

would generate

move register, 0
L1:
compare register, n
jump-if-greater-or-equal L2
-- body ..
increment register
jump L1
L2:

while the backward-counting code

for (i = n; --i>=0;){
  .. body ..
}

would generate

move register, n
L1:
decrement-and-jump-if-negative register, L2
.. body ..
jump L1
L2:

so inside the loop it's only doing two extra instructions instead of four.


I believe the reason is because you're comparing the loop end point against 0, which is faster then comparing again < length (or another JS variable).

It is because the ordinal operators <, <=, >, >= are polymorphic, so these operators require type checks on both left and right sides of the operator to determine what comparison behaviour should be used.

There's some very good benchmarks available here:

What's the Fastest Way to Code a Loop in JavaScript


It is easy to say that an iteration can have less instructions. Let’s just compare these two:

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

for (var i=length; i--;) {
}

When you count each variable access and each operator as one instruction, the former for loop uses 5 instructions (read i, read length, evaluate i<length, test (i<length) == true, increment i) while the latter uses just 3 instructions (read i, test i == true, decrement i). That is a ratio of 5:3.


What about using a reverse while loop then:

var values = [1,2,3,4,5]; 
var i = values.length; 

/* i is 1st evaluated and then decremented, when i is 1 the code inside the loop 
   is then processed for the last time with i = 0. */
while(i--)
{
   //1st time in here i is (length - 1) so it's ok!
   process(values[i]);
}

IMO this one at least is a more readble code than for(i=length; i--;)


for increment vs. decrement in 2017

In modern JS engines incrementing in for loops is generally faster than decrementing (based on personal Benchmark.js tests), also more conventional:

for (let i = 0; i < array.length; i++) { ... }

It depends on the platform and array length if length = array.length has any considerable positive effect, but usually it doesn't:

for (let i = 0, length = array.length; i < length; i++) { ... }

Recent V8 versions (Chrome, Node) have optimizations for array.length, so length = array.length can be efficiently omitted there in any case.