Quick Tip – Optimizing DOM Traversal

read 12 comments

The topic of optimization has come up a number of times in the jQuery mailing list. jQuery’s DOM traversal is powerful and easy, but it can sometimes be slow as well. As with any JavaScript library or framework, the helper methods will be slower than the plain old JavaScript (p.o.j) methods. Nevertheless, if we keep in mind the jQuery’s speed hierarchy, the speed difference between jQuery and p.o.j. will often be negligible.


The “speed hierarchy” goes like this, in order of fastest to slowest:

  1. ID : $(‘#some-id’)
  2. Element : $(‘div’)
  3. Class : $(‘.some-class’)

jQuery uses JavaScript’s native getElementById() to find an ID in the document. It’s fast — probably the single fastest way to find something in the DOM — because it’s only looking for a single unique thing, and it’ll stop looking once it has found it. So, if we have <h2 id="title">This is my title</h2>, we would use $('#title'), not $('h2#title') to access it.

To find a bare class name, as in #3 above, jQuery goes through every element in the entire DOM. To find an element, on the other hand, it uses getElementsByTagName(), thereby limiting the number of elements it has to traverse right from the start. Therefore, if we know which element the class is tied to, we can speed up the traversal significantly by referring to it, using, for example, $('div.some-class') rather than $('.some-class').

Likewise, we can help jQuery gather our classes faster if we can limit where jQuery looks to a particular ID: $('#sidebar .menu'), not $('.menu').

I’m sure there other ways to make DOM traversal speedier, so if anyone knows any other tricks, I’d love to see them in the comments. Also, I should probably reiterate that if speed is all you care about, no library/framework is going to beat p.o.j.

Update: Motivated by enej’s comment, I put together a little speed-test page where you can try out a number of different DOM queries and see how fast they are. Since I posted a link to the page on the jQuery mailing list, there has been quite a bit of activity in this area. Aaron Heimlich extended the speed test to work in conjunction with Firebug for some awesome reporting, and rumor has it that Yehuda Katz is working on an entire speed-test suite.

Update

Please be aware that these optimizations are not necessarily helpful as of jQuery 1.3 because of the new “Sizzle” selector engine.

comment feed

12 comments

  1. enej

    it would be nice to see some bench mark tests. as in what the difference is.. such as if you use $('#sidebar div.menu') if it is faster then $(#sidebar .menu)... did anyone do this allready?

  2. Thanks for mentioning this. Because I lack the long term experience of someone like yourself, topics like this can be very helpful for new comers to jQuery and JavaScript

    I’d appreciate it if you posted more tips like this in the future.

    Take care.

  3. enej, thanks for the suggestion. Please see my update to this entry for benchmark information.
    Adam, I’m glad you’re finding these tips helpful. Feel free to request any information that you want to do about this awesome library. If I can’t answer it, I’m sure that someone else in the jQuery community can.

  4. Great tips! Thanks for breaking speed hierarchy.

  5. enej

    No thank you Karl

    For your time and effort.

    Thanks again. It’s just interesting to see. I think I will try to come up with some test myself, Last summer I was working on a web app. and used jQuery quite a bit. and it really helped when I did something like $('#id div.feeditem') instead of just $(‘.feeditem’) impoved the whole loding of the page quite a bit. But if I do any more testing I will let you know. And Merry Xmas

  6. Tom

    Useful, all very useful! Great post, great site. Much obliged…

  7. Great stuff! Thanks.

  8. Frédéric Hewitt

    That’s no more exact since jQuery 1.3 and Sizzle, because it now works bottom-top.

    So $('#sidebar .menu') is not better (worst in fact) than just $('.menu'). But evidently, $(‘ul.menu’) still the best choice here.

    Well on other side, we can probably say than selector optimization is no more useful now for common situations.

    • Good points, Frédéric. Thanks. I’ve updated the post.

      • Is there somewhere where the Sizzle/jQuery 1.3.x selector optimization changes have been discussed? I only found a few mentions of the new “bottom-up” approach but nothing in detail. An in-depth explanation would be really helpful! Thanks.

      • jack

        I agree is there somewhere we can find an update on this great post? I’m using jquery 1.3

  9. Thank you for this Karl – it has helped me a lot: I wrote it up and gave props to you.

4 Pings

  1. jQuery Selector Speed…

    There’s an interesting discussion over on the jQuery mailing list about the speed of a couple basic selectors. The jist of it is:
    jQuery(“#myId”) is very fast because “#myId” gets turned into document.getElementById(“myId”).
    jQuery(“div#my…

  2. [...] be further optimized by using an id in addition to the element and class. As explained in this jQuery performance tip, jQuery’s DOM traversal processes id selection fastest, followed by element and class [...]

  3. [...] be further optimized by using an id in addition to the element and class. As explained in this jQuery performance tip, jQuery’s DOM traversal processes id selection fastest, followed by element and class selection. [...]

Sorry, but comments for this entry are now closed.