Comparing jQuery Selectors

We were talking with some colleagues the other day about some best practices we should follow for one of Backbase‘s products that we are building, namely Launchpad. We were considering a way of separating selectors we use for styling and selectors we use as hooks for JavaScript (like everyone should do). And I suggested a convention I use in my personal projects, which is having an attribute: data-hook to use for selecting elements in JavaScript.

And then, the issue of performance arose. Somebody said that attribute selectors are much slower than class selectors and we should avoid them. Of course this is correct, because class selectors are based on the native function getElementsByClassName. But the question still remained, about how much it would affect performance overall.

To test this, I got part of this website’s HTML. It is considered a bit small, but good enough for testing. The HTML consists of 106 nodes and the element we are going to have the selectors for is at 6-th level depth. I have put on the element an attribute: data-hook=”foo”, a class: .data-hook, and an id: #hook. To run the tests I used jsperf.com which is really an awesome tool. So, lets look at the result:

The results of course are like we expected, but the difference is really huge. Attribute selector is 10 times slower than class selector and 40(!!) times slower than the id selector. What amazed me though is how slow the tag selector is, even though there is a native function for it.

Out of curiosity, I decided to test against other browser. Namely Firefox, Internet Explorer 8 and the new Internet Explorer 10. The results were these:

jQuery selector speed results for Mozilla Firefox

jQuery selector speed results for IE8

jQuery selector speed results for IE10

Since this post isn’t about comparing browser speed, I’ll just go over quickly a few things to note. We can see that Firefox is about 2 times as slow as Chrome, and IE8 is about 10(!!) times. The weird thing comes with the new IE10. It has the same performance with Chrome for class selector, and is just a bit slower for the id selector. But it is almost 10 times as fast for the tag selector, which is really impressive. However, the attribute selector speed is really disappointing and even more disappointing is the fact there has been no improvement from IE8.

Ok, back to comparing selectors. These tests are OK  but what happens if we don’t select from the root of the element? What happens if we use a fast selector, to “restrict” the scope of the running selectors? In this scenario, let’s suppose we restrict the selection withing the article, thus starting from #post-47 (which could be a very realistic scenario). Essentially, instead of running $(‘[data-hook="foo"]‘), we will run $(‘#post-47 [data-hook="foo"]‘). Let’s see what happens in Chrome:

Now that was disappointing  Even the attribute selectors got slower. My guess is that this happened because it executes the most-right selector first and then still walks the tree upwards, trying to find the parent node. Which in our case is pretty useless too, since we have a unique node.

Now, one last test. What if we use the jQuery method find(). Let’s see what happened:

Much better! Essentially this way, the speed is tripled compared to our initial attribute selector! Tag name selector also got an impressive improvement too! Of course the id selector lost a lot of performance but that was a bit expected. Same for the class selector.

Conclusions

So, lets try to summarize a few things then

  • - Attribute selectors are the worst performing selectors of all
  • - Class selectors perform nicely on all browsers
  • - jQuery’s find() outperforms the css selectors.

After all this, my personal opinion is that this is not something to focus upon. To me this thing falls into the category of over-optimization. Since attribute selectors in JavaScript are not too common anyway, you should choose what you use based on your coding style, and keeping maintainability and code “cleanness” in mind. Buying a fraction of a second by changing all your selectors won’t mean that much anyway. Applying common sense and focusing on small details (eg. avoid selectors inside loops), will result in a much bigger performance gain than this.

N.

One Response to Comparing jQuery Selectors
  1. blerik Reply

    data-attributes are fast enough for Facebook (they call them sigils), so they should be fast enough for everybody :)

    http://www.phabricator.com/docs/javelin/article/Concepts_Sigils_and_Metadata.html
    http://stackoverflow.com/questions/6132963/what-is-the-data-sigil-html-attribute

Leave a Reply

Your email address will not be published. Please enter your name, email and a comment.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>