paldepind
paldepind

Reputation: 4880

Optimizing JavaScript loop makes it slower

In the book JavaScript Patterns Stoyan Stefanov he claims that the common way of looping in JavaScript

for (i = 0, max = myarray.length; i < max; i++) {
// do something with myarray[i]
}

can be optimized by using this pattern instead

for (i = myarray.length; i--;) {
// do something with myarray[i]
}

I found that to be interesting so I decided to test it in the real world by applying the technique to a performance intensive loop showed in this blog post about doing pixel manipulation with canvas. The benchmarks comparing the regular code with the "optimized" code can be seen here.

The interesting thing is that the supposedly optimized loop is actually slower than the regular way of looping in both Opera and Firefox. Why is that?

Upvotes: 0

Views: 132

Answers (3)

Jon Hanna
Jon Hanna

Reputation: 113382

To begin with, I see no reason why the second should be much faster than the first. The difference between comparing with zero versus comparing with another number is something that might make a difference in extremely tight loops in compiled code, but even there it's likely a cargo cult opt most of the time (read Richard Feyman's Cargo Cult Science if you don't get the reference, if nothing else it's a good read by there are also more than a few times where similar tendencies to copy something that worked well once to a case where there's no real reason to suppose it will help, in programming).

I could see the following being slower:

for (i = 0; i < myarray.length; i++) {
// do something with myarray[i]
}

But I could also see it not being slower, if the engine did the optimisation of hoisting the length check for you, or the implementation was such that checking the length and checking a variable was about equivalent cost anyway.

I could also see either that or the first code example you give, or perhaps both, being something that a given script-engine optimises - it is after all a very common idiom in js, and inherently involves looping, so it would be a sensible thing to try to detect and optimise for in a script engine.

Beyond such conjectures though, we can't really say anything about this beyond "because one works better in that engine than the other, that's why" without getting to the level below javascript and examining the implementation of the engine. Your very results would suggest that the answer won't be the same with each engine (after all, one did correspond more with what you expected).

Now, it's worth noting that in each case the results are quite close to each other anyway. If you found just one or two browsers that are currently reasonably popular where the change did indeed optimise, it could still be worth it.

If you're interested in whether it was ever worth or, or was just an assumption to being with, you could try to get a copy of Netscape 2 (first javascript browser ever, after all), and run some code to test the approach on it.

Edit: If you do try that sort of experiment, another is to try deliberately buggy loops that overshoot the array bounds by one. One possible optimisation for the engine is to realise you're walking the array, and check once on where you will end for out-of-range. if so, you could have different results if you will eventually error.

Upvotes: 1

Guffa
Guffa

Reputation: 700830

Most of the ways to try to optimise a loop comes from C, and a time when compilers where simpler and processors executed one instruction after the other.

Modern processors run the code very differently, so optimising specific instructions doesn't have the same effect now.

For Javascript the changes are quite rapid now. It has gone from being interpreted to being compiled, which makes a huge performance difference. The compilers are very different between browsers, and they change with each new browser version, so something that is faster in one browser today, may be slower tomorrow.

I have tested some different ways of optimising loops, and currently there is very little difference in performance: http://jsperf.com/loopoptimisations

One thing that can be said for certain though, is that the regular way of writing loops is the most common, so that is what all compilers will be focusing on optimising.

Upvotes: 1

Michael Borgwardt
Michael Borgwardt

Reputation: 346526

This kind of micro-optimization always has very limited validity. Chances are that the VM implementations include optimizations for the "common ways" of doing things that go beyond what you can do on the language level.

Which is why micro-optimizations are usually a waste of time. Beginners tend to obsess over them and end up writing code that is hard to maintain AND slow.

Upvotes: 3

Related Questions