Javascript Optimization: Looping and handling different ways in different browsers
In my quest to optimize my game engine I have discovered optimization i have been doing affecting each browser differently, in a lot of cases making one browser worse and the other better!
Currently I'm trying to optimize looping as i do alot of it and dep开发者_开发知识库ending on the way this is done can have a big effect on the performance of my engine.
Based on the results here http://jsperf.com/for-vs-while-loop-iterating/3
It seems a reverse for loop in chrome is the fastest
var l = foo.length;
for (var i = l; i--;) {
}
And in firefox a forward for loop is fastest
var l = foo.length;
for (var i = 0; i < l; i++) {
}
Now in order to use the correct one per browser I'm doing something like this
function foreach(func, iterations){
var browser = $.browser;
var i;
if (browser.webkit)
{
for(i=iterations;i--;)
{
func(i);
}
}
else
{
for (i = 0; i < iterations; i++)
{
func(i);
}
}
}
but it seems there may be alot of overhead here that may hurt performance.
If you were to provide different ways of looping for different browsers what would you do?
EDIT: seems there was a bug in my testing where i was doing one too many loops on the forward loop and now chrome seems to be the fastest there also, I may not need to optimize the loops but it may still be worth while as mention in another comment incase browser versions change performance again
Unfortunately, if your goal is the best performance loop on each browser, the very last thing you want to do is introduce function calls into it. There's no way you can define your foreach
function such that it will be anything like as fast as the straight for
loop. Calling the iteration function will wash out any gains you might get.
A quick jsperf can confirm this easily enough. For instance, run this one on Chrome or a recent version of Firefox or Opera. It compares looping forward with for
, backward with for
, or using the browser's built-in Array#forEach
function (part of ECMAScript5). (I think we can assume any foreach
function you build will be slower than the built-in one.) As you can see, the forEach
version is dramatically slower than either of the for
loops, which makes sense: Calling functions isn't very expensive, but it isn't free.
Mind you, what you're doing in the loop probably washes out the difference between counting up and count down. What I'd do is figure out what's fastest on the slower browsers, and use that. You said, for instance, that a reverse loop is faster in Chrome but a forward loop is faster in Firefox. As Chrome's V8 is dramatically faster than Firefox's SpiderMonkey (at the moment, these things are constantly in flux), pick the forward loop, as it's faster on the slower engine.
Otherwise, you're into needing to do preprocessing on your code and churning out a different version tailored to each browser.
I don't think your overhad is as big as you feel, but what you can do is do your test only once:
var foreach;
if (forwardIsFaster) {
foreach = function (func, iterations) {
// loop forwards...
};
} else {
foreach = function (func, iterations) {
// loop backwards...
};
}
That said, I'm not sure using browser sniffing is the best solution here; maybe instead do a test loop on startup, measure which solution is faster, and choose the one that turns out to be faster.
When you start doing something significant inside the loop (e.g. just printing the variable), the order of iteration doesn't matter, see:
http://jsperf.com/for-vs-while-loop-iterating/4
So stop caring about this and if (and only if) your code is slow in any place, just profile it and optimize that part.
You could make foreach
return a function, which would be an iterator. So you would have, once in your script, var iterator = foreach($.browser.webkit);
. From then on, you would just use iterator(iterations, callback)
, which would no longer be executing any conditionals.
The key, basically, is that the user's browser won't change, so the result of the execution of that conditional needs to be evaluated only once per script.
精彩评论