5

I know that in browser it is more optimal to write a for loop along the lines of

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

instead of

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

But is this true in NodeJS or does the V8 engine optimize it?

I know in ecma-262 5.1 sec-15.4 array length is defined as such:

The value of the length property is numerically greater than the name of every property whose name is an array index; whenever a property of an Array object is created or changed, other properties are adjusted as necessary to maintain this invariant.

Thus if the length doesn't change the only reason this method would be slower is because you have to access the property. What I'm looking for is a reasonable example/ explanation that would show whether or not the V8 engine (which is used in NodeJS) suffers in performance when accessing this property.

Sleep Deprived Bulbasaur
  • 2,368
  • 4
  • 21
  • 33

3 Answers3

5

If arr is a pure local variable and the loop doesn't touch it in any way, then yes. However even if the optimization fails, loading the same field over and over again doesn't really cost anything due to CPU cache.

Esailija
  • 138,174
  • 23
  • 272
  • 326
  • @Alnitak Doesn't matter how big or small it is, it is stored 12/24 bytes away from the array pointer which fits in all CPU cache lines – Esailija Dec 22 '14 at 14:57
  • sure, if the JIT is clever enough to perform that optimisation for the array object, and optimise away the property access too. My argument would be, if you know the loop length doesn't change, then _why not_ write the loop that way and allow even the dumbest JS interpreter to take advantage of the invariant. – Alnitak Dec 22 '14 at 14:59
  • @Alnitak it's not about optimization, V8 represents all arrays this way. – Esailija Dec 22 '14 at 15:00
  • I suppose my question is specifically about the V8 compiler, do you have any supporting resources? @Esailija – Sleep Deprived Bulbasaur Dec 22 '14 at 15:05
  • it's just the first one I found. Do you have a better performance test framework available? :) – Alnitak Dec 22 '14 at 15:06
  • I had to go Christmas shopping so ill check it later – Esailija Dec 22 '14 at 15:14
  • 2
    I would like to add that if hoisting of `arr.length` fails V8 will still have to reload length e.g. for a bounds check - so eliminating one explicit length load manually doesn't in fact eliminate all accesses to length property, implicit ones will remain. In this case hoisting one access manually can actually lead to a worse code, because you end up with two "unconnected" live values - more live values, higher register pressure and potentially more spill/restore code. – Vyacheslav Egorov Dec 22 '14 at 16:49
3

I would always use the first if applicable because it informs both the interpreter and any future reader of the code that the loop does not modify the length of the array.

Even if it's not faster (although http://jsperf.com/array-length-vs-cached suggests it actually is) it's simply good practise to factor constant expressions from outside of a loop.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
1

The problem is length's calculation. In this example for(var i=0; i<arr.length; i++){ } statement arr.length will be calculated at every loop iteration. But with for(var i=0, l=arr.length; i<l; i++){ } value will be taken without any calculations. Simply getting a value is faster than calculating length of the array.
Getting length can't be optimized by any compiler because it could be changed. So it's calculated each iteration.

Kiril
  • 2,935
  • 1
  • 33
  • 41