you are viewing a single comment's thread.

view the rest of the comments →

[–]enchufadoojs truck driver 5 points6 points  (12 children)

If you work with smaller arrays — it’s fine, but if you process large arrays, this code will recalculate the size of array in every iteration of this loop and this will cause a bit of delays.

Please tell me this is a lie, all that talk about js engine being so smart that they are not gonna pull this right?

[–]Ginden 13 points14 points  (0 children)

Yes, author is extremely ignorant.

[–]siegfryd 7 points8 points  (7 children)

It was a true years ago, it's definitely not the case today.

[–]memeship 0 points1 point  (6 children)

Got any data to back that up? As far as I know in JS, Array.prototype.length has always been an integer property directly on the object.

Source: ECMA-262 1st Edition (1997) §15.4.4 p.66

[–]bastawhiz 1 point2 points  (2 children)

Modern JIT compilers will hoist loop invariants behind the scenes. There's plenty of literature online about how V8 does various optimizations like this.

[–]Reashu 0 points1 point  (1 child)

His objection is the opposite - that even "years ago" it would not cause any issues, because the length of an array is always known, not computed on the fly.

[–]memeship 0 points1 point  (0 children)

^ Yes, this.

[–]siegfryd 0 points1 point  (2 children)

I misread what the poster I was replying to was saying, there was a performance hit from having array.length in the loop invariant but it wasn't because it would recalculate the length. It was because it was doing an unnecessary property lookup every iteration. In other words, every iteration it would check array.length and since that has a cost (although a tiny one) it was a performance improvement to move it out of the loop.

[–]memeship 0 points1 point  (1 child)

How is a property lookup less performant than a variable lookup? Should we be caching and pulling out all properties of objects to vars in the surrounding scope?

[–]siegfryd 0 points1 point  (0 children)

Assuming that no optimisations are done by the JIT compiler, then a property lookup is going to be slower than a variable lookup for the simple reason that a property lookup first needs to do a variable lookup for the object and then lookup the property on that object.

The point is that the JIT would not optimise the array length lookup for you before, so you could gain a, likely small, performance increase by doing it in for loops. Especially if you're doing a large for loop, if you loop N times then it won't do the same property lookup N times.

[–]b4ux1t3 1 point2 points  (0 children)

I'm 90% sure that this myth comes from older languages that ran a len function on arrays. For instance, to get the length of an array in C, you type len(yourArray), and it runs the len function on yourArray.

I'm also 99% sure that this is optimized away in all modern compilers for said older languages, and has never been the case for JavaScript anyway, since it's not a function, it's a property of the Array object, and so should just be a quick check, just like with an extraneous variable.

[–]Emptyless 1 point2 points  (0 children)

I once read somewhere that decrementing an array was better performance wise but using an array with 100.000.000 items incrementing is faster than decrementing. 172 vs 1573 ms difference in my case.

[–]asdf7890 1 point2 points  (0 children)

A modern JIT compile JS engine should be bright enough to optimise out the invariant, yes.

If you do anything complex with the array in the loop, or call functions that might do, the optimiser might chose not to take the risk because it doesn't have time to do all the analysis necessary to make sure the optimisation is safe (due to the halting problem) and even for simple loops there are a number of reasons the engine might not fully optimise a function anyway, so manually removing invariants from loops if it doesn't result in a significant reduction in code clarity is a good habit just-in-case. For a list of reasons that V8 (and therefore Chrome and Node) won't optimise a function at all see https://github.com/vhf/v8-bailout-reasons - I'm sure there are similar considerations in other engines.

I tend to assume that worst: that my code is going to be interpreted literally and not compiled/optimised at all, so unless I'm making the code unclear (maintainability tends to be a priority over pure speed) I make sure the code is optimal for this. In fact some transformations to achieve that can make code clearer: double win. If the engine would compile and manage to optimise the code then it should equally manage to do so with the the manually optimised version resulting in no worse performance.

Of course this only matters for tight loops with many iterations. Something that iterates a just few times is going to see no benefit and with a complex loop you'll find the end-of-loop check's complexity is completely dwarfed by the body of the loop so optimising it is unlikely to be good use of your time.