We can probably special case the querySelector API in the simple cases where one passes an ID, a class name, or a tagname to it. this was suggested in http://www.glazman.org/weblog/dotclear/index.php?post/2010/09/29/Why-is-getElementsByTagName-faster-that-querySelectorAll.
Note that Webkit has such an optimization for a single ID for cases when there's only one element with that ID in the document. That'd be reasonably simple to add, but are there actual non-microbenchmark use cases? Also, are there any numbers on what the speedup looks like for, say, tagnames? (Note that I have local patches that make querySelectorAll about 2x faster, btw; they just have a few kinks to work out).
(In reply to comment #1) > Note that Webkit has such an optimization for a single ID for cases when > there's only one element with that ID in the document. That'd be reasonably > simple to add, but are there actual non-microbenchmark use cases? Yes, I'd expect so. If libraries such as jQuery use querySelector as their implementation for style queries, this might have real world performance improvement results.
That's an if, though. Last I checked, jquery parsed the selector itself, pulled bits of it apart, passed some of it through to getElementById, some to querySelector, and some to its internal selector implemenation..... Has that changed?
That said, I'm still interested in the numbers; if there's a testcase I could even test on it with the changes I mention in comment 1.
Here's a test on JSPerf: http://jsperf.com/getelementsbytagname-a-0-vs-queryselector-a Note that getElementsByTagName("a") is much faster that querySelector("a"). I'm guessing this is likely due to caching of the NodeList results, but would be nice if the results were closer. :)
Thanks for writing that test! A few things: 1) document.getElementsByTagName("a") and document.querySelector("a") can return different nodes; they're not equivalent calls. So comparing them to each other is a little weird. That said, the behavior difference is actually likely to make querySelector a tad faster if all else were equal. What you really want to compare to, if you're comparing querySelector("a"), is getElementsByTagNameNS("*", "a"). I created a revision 2 of the test that does that, but not sure how to publish it. 2) The nodelist caching is in fact the most likely thing that's helping here; this test is more or less bogus in that regard (should be using different tag names on every iteration if it wants a useful comparison). I didn't write a test for this, because doing it right (e.g. without Math.random() or string concatenation dominating the time so that the test becomes useless) involves understanding the test harness guts sufficiently to know how it calibrates its loops. 3) It would be interesting to see how much of the speed difference is due to the fact that querySelector has to parse the selector. You could test that by calling it on a node that has no kids, possibly. Or profiling. Hard to tell. Note that any sort of fast-path would need to either parse the selector or have a parsed-selector cache; we could do the latter without creating the fast-paths this bug suggests. 3) The numbers I get for the querySelector part of this test are incredibly noisy (factor of 2 noise in them). 4) "Usually" the numbers I get on trunk are: 1,354,050 and 427,781 4) With a build that has the patch I mention in comment 1, I "usually" get: 1,569,725 and 595,782 I have no idea why that first number changed in the process. 5) Is there a way I can make this harness let me run a snippet of code right before starting the testing loop for one of these tests and again right after the loop ends? If I could do that, I could answer the question from item 2, say.
The site itself isn't setup for a lot of optimization, though I'm sure if you grab the source of the page you can get it to run in any way you'd like. Probably not the place to ask, but I am curious as to why getElementsByTagName("a") could return a different node than querySelector("a").
> though I'm sure if you grab the source of the page you can get it to run in any > way you'd like Well, sure. It's all software. I was sort of hoping for a simple enough way that I could justify spending the time on it in addition to blockers.... ;) For the other, getElementsByTagName matches on the qualified name, while querySelector matches on the local name. So any time there's a non-null namespace prefix they'll do different things. Though there's talk of changing this getElementsByTagName behavior, note.
We added a fast-path for the id case in bug 696205, for what it's worth.
Summary: optimize querySelector(All) for cases like querying an ID, a class name or a tag name → optimize querySelector(All) for cases like querying a class name or a tag name
Bug 1410624 did this.
Status: NEW → RESOLVED
Last Resolved: a year ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.