Hacker News new | ask | show | jobs
by blymphony 2060 days ago
Isn't it a good habit to store the length of the array regardless of browser implementation? Technically, accessing a variable is simply faster than a property access on an object, and this wouldn't be a case of premature optimization either--just sound coding practice.
6 comments

They're close enough not to matter on most modern browsers - I suspect V8 actually hoists the field access out of the loop when it compiles it (loop-invariant code motion is a really well-understood compiler optimization at this point). I would definitely put this in the premature optimization bucket.

It doesn't really matter nowadays anyway, because now I write my for-each loops like:

  for (let elem : arr) { ... }
or

  arr.foreach(elem => { ... });
(Well, technically now I write Android & C++ code and do leadership/communication stuff, but I brushed up on my ES6 before getting the most recent job.)

    for (let elem of arr) {}
is actually quite a bit slower than

    for (let i = 0; i < arr.length; i++) {}
because the people who built the JS spec decided that there should be a brand new heap object created every iteration. At the time, there was thought that escape analysis would let them optimize away this object, but from what I can tell, ten years later, engines are really bad at it. Escape analysis is a heuristic, and it needs to be conservative.

And yes, this isn't a micro-benchmark. At least in my application, performance is mostly bounded from GC pauses and collection, not slow code execution. Anything to reduce your GC pressure is going to be a good improvement... but note that modern frameworks like React are already basically trashing your heap, so changing out your loops in an already GC-heavy codebase won't really do much.

It can only hoist the length out of a for loop if it can prove that the length doesn't change, i.e. the array isn't modified. Otherwise it does have to check it each iteration. This is pretty hard in general since any time you call an external function it could potentially have a reference to the array and modify it.

I suspect the length access is just so fast that the difference between hoisting it out and not is immeasurable.

> for (let elem : arr) { ... }

Do you mean:

  for (let elem of arr) { ... }

Unless this is a joke about writing in Java & C++ (for which the colon syntax is valid) instead of javascript.
But

   arr.foreach(elem => { ... });
is still always much slower than a for loop, having the callback call, isn't it?
That very much depends on how good the JIT is, certainly many AOT compilers would understand this pattern and inline the callback, resulting in very similar optimised code.
In cases where order doesn't matter you can avoid you can avoid the array length question all together by decrementing:

    let index = arr.length;
    do {
        index -= 1;
        console.log(arr[index]);
    } while (index > 0);
As a side note whether it takes longer to access a variable or object property is largely superficial depending upon the size of object because it implies creating a new variable on which to store that object property. There is time involved to invoke a new variable just as there is time involved to access an object's property.

As an added bit of trivia in the 1970s a software developer named Paul Heckel, known for Heckel Diff algorithm, discovered that access to object properties is faster than accessing array indexes half the time. That was in C language, but it holds true in JavaScript.

In 2009 we standardized on this form for all Google Search JS for-each loops, because we were literally counting bytes on the SRP:

  for(var i=0,e;e=a[i++];){ ... }
Could result in problems if the array contained falsey values, but we just didn't do that.

Nowadays, like I mentioned above, I'd just do

  arr.foreach((elem, i) => { ... });
Which last time I checked was significantly slower than the for-loop, but I've learned my lesson about trying to optimize for browser quirks that may disappear in a year or two. :-)
>[...] discovered that access to object properties is faster than accessing array indexes half the time. That was in C language, but it holds true in JavaScript.

What are these object properties in C?

Hash map then.
Hm. So you're saying that indexing into a hash map can be faster than indexing into an array? How would this be possible? I mean, under the hood a hash map is going to an array too, which is being indexed based on the hash value...
Hash map properties are randomly accessed from memory opposed to array indexes.
If the code is hot, there is no perf difference in modern JavaScript engines. They will speculate and both your var access and length property access turn into just simple a memory read or a constant.
Any compiler worth its salt should do that optimization for you.
> Technically, accessing a variable is simply faster than a property access on an object

A good compiler will make it so that they are largely equivalent. In C-based languages this is one of the first things a compiler will do, and I am sure that every JavaScript engine does this kind of thing too when possible (actually, it may even have an easier time doing it because it may be able to skip pointer analysis).

If it can proved immutable all modern JS engines will at worst hoist to the earliest point of immutability. With the exciting amount of inlining the modern JS JITs can do they can often do a better job of proving immutability than C[++] compilers.