views:

351

answers:

6

Hi,

I've been looking through a lot of Javascript Optimizing and most of them talk about string concatenation and a few other big ones found here, but I figured there had to be more details that you can optimize for when speed is critical and the processing of those pieces of code is very high.

Say you run this code for some reason: (unlikely, I know, but bear with me)

for( var i = 0; i < 100000000000; i++ ) {
  //Do stuff
}

And there's no way of getting around having a loop that big... You're going to want to make sure that all the stuff you're doing in that loop is optimized to the point that you can't optimize it anymore... or your website will hang.

Edit: I'm not necessarily talking about a loop, what about a function that's repeatedly called such as onmousemove? Although in most cases we shouldn't need to use onmousemove, there are some cases that do.
This questions is for those cases.

Using JQuery as our JS library

So what I would like is tips for optimizing, but only the more uncommon ones
- ie. Speed differences between switch or if-else

If you'd like to see the more common ones, you can find them here:

A: 

Store long reference chains in local variables:

function doit() {
    //foo.bar.moo.goo();
    //alert(foo.bar.moo.x);

    var moo = foo.bar.moo;

    moo.goo();
    alert(moo.x);
}
Ates Goral
Even if there is no reference chain, assigning a local variable to one outside the current scope is still beneficial in loops, because JavaScript looks for variables first in current scope, then in parent scope, and so on.
Blixt
+4  A: 

"And there's no way of getting around having a loop that big... "

In the real world of RIA, you HAVE to get around the big loops. As important as optimization is learning how to break large loops into small loops, and giving time to the browser to deal with its UI. Otherwise you'll give your users a bad experience and they won't come back.

So I'd argue that BEFORE you learn funky JS optimizations, you should know how to break a large loop into chunks called by setTimeout() and display a progress bar (or let animated GIFs loop).

Perceived speed is often more important than actual speed. The world of the client is different from the world of the server.


When animating, learn how to find out if you're running on a lame browser (usually IE) and try for a worse framerate (or just don't animate). I can get some animations to go 90fps in a good browser but just 15fps in IE. You can test for the browser, but it's usually better to use timeouts and the clock to see how animations are performing.


Also, for genuine speedups, learn how to use web workers in Gears and in newer browsers.

Nosredna
This isn't about loops necessarily. What if it's a function that gets called a lot? For example, a onmousemove event, even if the function is short it still slows down processing.
Matt
@Matt: In most cases you won't probably end up needing to do something on while the mouse is moving or window is resizing(IE). You'd just need to do stuff when it has ended. In that case, you can defer the execution of your handler so that it runs only once. See this - http://ajaxian.com/archives/delaying-javascript-execution
Chetan Sastry
@Chetan Sastry: I was giving onmousemove event as an example because my site uses on mouse move. Think of something similar to auto displaying the mouse coordinates as it moves, only a lot more complicated. Please don't dismiss questions based on "most cases", if everyone did that, those question that didn't fall under the category of "most cases" would never be solved.
Matt
@Matt: I didn't dismiss your question. I just answered a specific case where people tend to think they need to keep a constant track of every mouse move but in reality, a start and end point is just what they need. If your case is doesn't fall under the category, ignore. Others can still see your question and will answer, hopefully
Chetan Sastry
So it's not a loop, and it's not onmousemove. It's very hard to answer a moving target. Different situations call for different techniques.
Nosredna
It is an onmousemove see my second comment: "because my site uses on mouse move."
Matt
In that case, instead of doing the processing in mousemove, you can just use the mousemove event to save to a history of mouse events and use a timer to do processing. That would keep you from getting the UI all gummy-acting
Nosredna
+2  A: 

If it doesn't need to be synchronous, convert the loops into a recursive implementation with setTimeout calls

for( var i = 0; i < 100000000000; i++ ) {
    //Do stuff
}

Can probably written as

function doSomething(n)
{
    if (n === 0) return some_value;
    setTimeout(function(){doSomething(n-1);}, 0);
}

OK, this might not be a good example, but you get the idea. This way, you convert long synchronous operations into an asynchronous operation that doesn't hang the browser. Very useful in certain scenarios where something doesn't need to be done right away.

Chetan Sastry
More on this is here: http://stackoverflow.com/questions/957810/ui-responsiveness-and-javascript/958210#958210
zakovyrya
A: 

Which JavaScript engine are we supposed to be targeting? If you're talking about such extreme optimisation, it makes a big difference. For starters, I'll point out that the array.join() trick for string concatenation is only really applicable to Microsoft's JScript engine; it can actually give worse performance on other JS engines.

NickFitz
There's a good argument to be made that it's really only IE that you need to optimize for. If you get it running fast on IE, it'll be plenty fast in the other browsers.
Nosredna
A: 

Using split & join instead of replace:

//str.replace("needle", "hay");
str.split("needle").join("hay");
Ates Goral
A: 

After seeing a few good answers by the people here, I did some more searching and found a few to add:

These are tips on Javascript optimizing when you're looking to get down to the very little details, things that in most cases wouldn't matter, but some it will make all the difference:

Switch vs. Else If

A commonly used tactic to wring whatever overhead might be left out of a large group of simple conditional statements is replacing If-Then-Else's with Switch statements.

Just incase you wanted to see benchmarking you can find it here.

Loop Unrolling

To unroll a loop, you have it do more than one of the same step per iteration and increment the counter variable accordingly. This helps a lot because you then decrease the number of times you are checking the condition for the loop overall. You must be careful when doing this though because you may end up overshooting bounds.

See details and benchmarking here.

Reverse Loop Counting

Reverse your loop so that it counts down instead of up. I have also seen in various documents about optimization that comparing a number to zero is much quicker than comparing it to another number, so if you decrement and compare to zero it should be faster.

See more details and benchmarking here.

Duff's Device
It's simple, but complicated to grasp at first. Read more about it here.
Make sure to check out the improved version further down that page.

The majority of this information was quoted directly from here: JavaScript Optimization. It's interesting, since it's such an old site it looks at optimization from the perspective of the browser processing power they had back then. Although the benchmarks they have recorded there are for IE 5.5 and Netscape 4.73, their benchmarking tools give accurate results for the browser you're using.

For the people who think these details don't matter, I think it says a bit about the way people perceive the power in advancing technologies we have. Just because our browsers are processing many times faster than what they use to doesn't necessarily mean that we should abuse that processing power.

I'm not suggesting spend hours optimizing two lines of code for 0.005ms, but if you keep some these techniques in mind and implement them where appropriate it will contribute to a faster web. After all, there are still many people using IE 6, so it would be wrong to assume everyone's browsers can handle the same processing.

Matt