views:

5741

answers:

13

I'm looking for any way that I can improve the selector performance of a jQuery call. Specifically things like this:

Is $("div.myclass") faster than $(".myclass")

I would think it might be, but I don't know if jQuery is smart enough to limit the search by tag name first, etc. Anyone have any ideas for how to formulate a jQuery selector string for best performance?

A: 

I've been on some of the jQuery mailing lists and from what I've read there, they most likely filter by tag name then class name (or vice versa if it was faster). They are obsessive about speed and would use anything to gain a smidgen of performance.

I really wouldn't worry about it too much anyway unless you are running that selector thousands of times/sec.

If you are really concerned, try doing some benchmarking and see which is faster.

Ryan Doherty
+21  A: 

There is no doubt that filtering by tag name first is much faster than filtering by classname.

This will be the case until all browsers implement getElementsByClassName natively, as is the case with getElementsByTagName.

kamens
But even if the browser implements that function it would still be faster to filter by tag name too right?
Hoffmann
I have updated http://www.componenthouse.com/article-19 from Jeffs response to use the latest jQuery, it seems that from the second test A and B have the same performance in Opera 10 and firefox 3.5. I couldn't make it work on IE8 (I haven't tried much though). So it seems that I was wrong on my previous comment.
Hoffmann
@hoffmann, probably not. If we assume both of these functions are implemented with b-trees I don't see why getElementsByClassName would be any slower... You'd still have to build the index prior to being able to use that function...
Evan Carroll
+27  A: 

jQuery performance analysis of selectors

http://www.componenthouse.com/article-19

short story: finding an element by id is much faster than the other methods -- at least in that test.

Jeff Atwood
That was just what I needed. I've got a few performance problems on a jQuery heavy page.
CMPalmer
Wow, very interesting. I was just about to ask this question.
Hoffmann
I did some testing and it seems that $("p#ID") has the same speed as $p("#ID"). Probably the only difference in speed is the insignificantly slower regex parsing in the first
Hoffmann
+3  A: 

I'll add a note that in 99% of web apps, even ajax heavy apps, the connection speed and response of the web server is going to drive the performance of your app rather than the javascript. I'm not saying the you should write intentionally slow code or that generally being aware of what things are likely to be faster than others isn't good.

But I am wondering if you're trying to solve a problem that doesn't really exist yet, or even if you're optimizing for something that might change in the near future (say, if more people start using a browser that supports getElementsByClassName() function referred to earlier), making your optimized code actually run slower.

Joel Coehoorn
A: 

Consider using Oliver Steele's Sequentially library to call methods over time instead of all at once.

http://osteele.com/sources/javascript/sequentially/

The "eventually" method helps you call a method after a certain period of time from its initial call. The "sequentially" method lets you queue several tasks over a period of time.

Very helpful!

Evan Moran
+2  A: 

Another place to look for performance information is Hugo Vidal Teixeira's Performance analysis of selectors page.

http://www.componenthouse.com/article-19

This gives a good run down of speeds for selector by id, selector by class, and selector prefixing tag name.

The fastest selectors by id was: $("#id")

The fastest selector by class was: $('tag.class')

So prefixing by tag only helped when selecting by class!

Evan Moran
+7  A: 

In some cases, you can speed up a query by limiting its context. If you have an element reference, you can pass it as the second argument to limit the scope of the query:

$(".myclass", a_DOM_element);

should be faster than

$(".myclass");

if you already have a_DOM_element and it's significantly smaller than the whole document.

Matthew Crumley
+3  A: 

Here is how to icrease performance of your jQuery selectors:

  • Select by #id whenever possible (performance test results ~250 faster)
  • Specify scope of your selections ($('.select', this))
jQuery Lover
+5  A: 

In order to fully comprehend what is faster, is you have to understand how the CSS parser works.

The selector you pass in gets split into recognizable parts using RegExp and then processed piece by piece.

Some selectors like ID and TagName, use browser's native implementation which is faster. While others like class and attributes are programmed in separately and therefore are much slower, requiring looping through selected elements and checking each and every class name.

So yes to answer your question:

$('tag.class') is faster than just $('.class'). Why? With the first case, jQuery uses the native browser implementation to filter the selection down to just the elements you need. Only then it launches the slower .class implementation filtering down to what you asked for.

In the second case, jQuery uses it's method to filter each and every element by grabbing class.

This spreads further than jQuery as all javascript libraries are based on this. The only other option is using xPath but it is currently not very well supported among all browsers.

Dmitri Farkov
A: 

A great tip from a question I asked: Use standard CSS selectors wherever possible. This allows jQuery to use the Selectors API. According to tests performed by John Resig, this results in near-native performance for selectors. Functions such as :has() and :contains() should be avoided.

From my research support for the Selectors API was introduced with jQuery 1.2.7, Firefox 3.1, IE 8, Opera 10, Safari 3.1.

Alex Angas
A: 

If I am not mistaken, jQuery also is a bottom up engine. That means $('#foo bar div') is a lot slower than $('bar div #foo'). For example, $('#foo a') will go through all of the a elements on the page and see if they have an ancestor of #foo, which makes this selector immensely inefficient.

Resig may have already optimized for this scenario (it wouldn't surprise me if he did - I believe he did in his Sizzle engine, but I am not 100% certain.)

Reid
A: 

I believe that selecting by ID first is always faster:

$("#myform th").css("color","red");

should be faster than

$("th").css("color","red");

However, I wonder how much chaining helps when starting with the ID? Is this

$("#myform").find("th").css("color","red")
.end().find("td").css("color","blue");

any faster than this?

$("#myform th").css("color","red");
$("#myform td").css("color","blue");
Lawrence