Infrequently Noted

Alex Russell on browsers, standards, and the process of progress.

Comments for Dojo's Query System: No, Really, It's That Fast


"...although there’s really no reason why your query engine of choice should be twice as slow as Dojo’s..."

Wouldn't that imply, then, that if Dojo's query engine was twice as slow as another engine, at the same metrics, there wouldn't be much reason for using Dojo, would there?

"Now that we’re all fast enough"

I'd agree that selector engines are rapidly approaching a solid level (especially with the Selectors API in play) - but that's a very tiny aspect of most web applications. In our "in-the-wild" profiling we've found that DOM manipulation and construction still consume the vast majority of page rendering time. Libraries are definitely not out of the woods yet when it comes to pure-JavaScript/DOM library performance.

John:

Well, it would imply that Dojo would have a bug to fix, in the same sense that it's a bug that the other libraries haven't adopted our query engine code. For instance, there's this:

http://bugs.dojotoolkit.org/ticket/7072

Which affects our Slickspeed results such that Dojo appears to be much slower than some other libraries when in fact it's just a single (rarely used) selector which is well outside the norm in terms of the performance profile. Omitting that selector, Dojo's design on the DOM branch of the query engine wins by a handy margin.

Anyway, we'll gladly agree that query speed isn't anyone's bottleneck. Would be great, then, to see libraries not use it as a benchmarketing baseline.

Regards

by alex at
Michael:

I'd love to see your test case. I have a strong suspicion that the time to execute the queries wasn't a blocker (unless the queries weren't well thought-out) vs. the time to create and apply the function handlers (which includes lots of object alloc and opportunities for overhead creation).

Regards

by alex at
I don't quite agree. I know that we have had huge problems with performing a number of queries as part of event bindings during page-load. Page load time was unacceptable and we had to switch to inline event binding instead. That made a huge difference. A constant-time query would have made all the difference.
Michael:

I'd agree with Alex's comments. Also, keep in mind that events bubble and you can reduce the number of event handlers by observing them at the parent/ancestors.

by Les at
Hey Ray:

So the query compilation is a very big part of it, but fetching previously matched elements is a no-go for reasons of accuracy and a lack of mutation events in browsers. Every JS library worth its salt uses some form of query-to-function builder. Indeed, Dojo's vanilla engine is a closure-based function accumulator (making it super-hackable) married to a left-to-right term matching core. For browsers which have much faster engines built in, Dojo defers to those engines (be they XPath or querySelectorAll), but keeps a record of the decisions regarding which engine to use (again, via a closure).

I think it would absolutely be great to see some benchmarks which target unique query runs, but the Dojo engine might do "artifically" well here as well since we compile and cache the matchers for sub-expressions as well, allowing us to do even better in the real-world where many queries might differ only by one or two terms. Fundamentally, I think the best benchmarks will be related to queries culled from heavy query users based on real-world DOMs and DOM fragments in a "clean" environment (iframe, most likely).

But the whole point here, I guess, is that while Dojo might totally own on those benchmarks, the time is quickly passing when it will even matter. In fact, I think benchmarketing on this basis is probably already past its due-date. Time to move on to talk about issues of larger-scale application construction and composition (another area where Dojo's performance and tooling focus pays off in a big way, but that's another discussion entirely).

Regards

by alex at
I haven't looked at the specifics of how these speed improvements are being made, but if they are being made through aggressive caching of compiled queries and previously fetched elements, might I suggest an alternative benchmark that focuses on startup time of a page, which could negate some of the cache advantages.

That is, if I've gone a ton of disjoint queries, the benchmarks might show great performance if the same query is replayed over and over again, but it could still be the cache that all the selector queries are adding some non-trivial startup time latency, especially if the difference between a query never seen before, and one which is cached, are huge.

Now, I know someone crazy is going to suggest caching these in window.name, cookies, or gears soon. :)