I have been writing a JS algorithm. Its blazing fast in chrome and dog slow in FF. In the chrome profiler, I spend <10% in a method, in FF the same method is 30% of the execution time. Are there javascript constructs to avoid because they are really slow in one browser or another?
One thing I have noticed is that things like simple variable declaration can be expensive if you do it enough. I sped up my algorithm noticable by not doing things like
var x = y.x;
dosomthing(x);
and just doing
dosomething(y.x)
for example.
As you’ve found, different things are issues in different implementations. In my experience, barring doing really stupid things, there’s not much point worrying about optimizing your JavaScript code to be fast until/unless you run into a specific performance problem when testing on your target browsers. Such simple things as the usual “count down to zero” optimization (
for (i = length - 1; i >= 0; --i)instead offor (i = 0; i < length; ++i)) aren’t even reliable across implementations. So I tend to stick to writing code that’s fairly clear (because I want to be nice to whoever has to maintain it, which is frequently me), and then worry about optimization if and when.That said, looking through the Google article that tszming linked to in his/her answer reminded me that there are some performance things that I tend to keep in mind when writing code originally. Here’s a list (some from that article, some not):
When you’re building up a long string out of lots of fragments, surprisingly you usually get better performance if you build up an array of the fragments and then use the
Array#joinmethod to create the final string. I do this a lot if I’m building a large HTML snippet that I’ll be adding to a page.The Crockford private instance variable pattern, though cool and powerful, is expensive. I tend to avoid it.
withis expensive and easily misunderstood. Avoid it.Memory leaks are, of course, expensive eventually. It’s fairly easy to create them on browsers when you’re interacting with DOM elements. See the article for more detail, but basically, hook up event handlers using a good library like jQuery, Prototype, Closure, etc. (because that’s a particularly prone area and the libraries help out), and avoid storing DOM element references on other DOM elements (directly or indirectly) via expando properties.
If you’re building up a significant dynamic display of content in a browser,
innerHTMLis a LOT faster in most cases than using DOM methods (createElementandappendChild). This is because parsing HTML into their internal structures efficiently is what browsers do, and they do it really fast, using optimized, compiled code writing directly to their internal data structures. In contrast, if you’re building a significant tree using the DOM methods, you’re using an interpreted (usually) language talking to an abstraction that the browser than has to translate to match its internal structures. I did a few experiments a while back, and the difference was about an order of magnitude (in favor ofinnerHTML). And of course, if you’re building up a big string to assign toinnerHTML, see the tip above — best to build up fragments in an array and then usejoin.Cache the results of known-slow operations, but don’t overdo it, and only keep things as long as you need them. Keep in mind the cost of retaining a reference vs. the cost of looking it up again.
I’ve repeatedly heard people say that accessing vars from a containing scope (globals would be the ultimate example of this, of course, but you can do it with closures in other scopes) is slower than accessing local ones, and certainly that would make sense in a purely interpreted, non-optimized implementation because of the way the scope chain is defined. But I’ve never actually seen it proved to be a sigificant difference in practice. (Link to simple quick-and-dirty test) Actual globals are special because they’re properties of the
windowobject, which is a host object and so a bit different than the anonymous objects used for other levels of scope. But I expect you already avoid globals anyway.Here’s an example of #6. I actually saw this in a question related to Prototype a few weeks back:
In Prototype,
$$does an expensive thing: It searches through the DOM tree looking for matching elements (in this case, elements with the class “foo”). The code above is searching the DOM three times on each loop: First to check whether the index is in bounds, then when checking whether the element has the class “bar”, and then when setting the style.That’s just crazy, and it’ll be crazy regardless of what browser it’s running on. You clearly want to cache that lookup briefly:
…but taking it further (such as working backward to zero) is pointless, it may be faster on one browser and slower on another.