Implementing the Sizzle Selector Engine in MooTools

By  on  

jQuery creator John Resig released his Sizzle selector engine. MooTools rightfully opted not to use Sizzle for a variety of reasons:

  • Sizzle currently offers no speed improvements over MooTools' current selector engine. (John Resig commented about this below.)
  • The MooTools team would have to give up a level of control over its own framework.
  • Sizzle doesn't follow MooTools' strict coding standards.

I agree completely with the Valerio's decision but you may not. Here's how you can implement Sizzle as MooTools' selector engine.

The MooTools / jQuery JavaScript

//just as reader "Ryan" mentioned....
Window.$$ = function(selector){
	return new Elements(new Sizzle(selector));
}

I'll go on record saying that Valerio's post was poetic and 100% on the money: Sizzle is not the answer to a question that hasn't already been answered. MooTools' selector engine is fast and highly extensible.

Recent Features

  • By
    Write Better JavaScript with Promises

    You've probably heard the talk around the water cooler about how promises are the future. All of the cool kids are using them, but you don't see what makes them so special. Can't you just use a callback? What's the big deal? In this article, we'll...

  • By
    CSS @supports

    Feature detection via JavaScript is a client side best practice and for all the right reasons, but unfortunately that same functionality hasn't been available within CSS.  What we end up doing is repeating the same properties multiple times with each browser prefix.  Yuck.  Another thing we...

Incredible Demos

  • By
    Chris Coyier’s Favorite CodePen Demos IV

    Did you know you can triple-heart things on CodePen? We’ve had that little not-so-hidden feature forever. You can click that little heart button on any Pen (or Project, Collection, or Post) on CodePen to show the creator a little love, but you can click it again...

  • By
    Style Textarea Resizers

    Modern browsers are nice in that they allow you to style some odd properties.  Heck, one of the most popular posts on this blog is HTML5 Placeholder Styling with CSS, a tiny but useful task.  Did you know you can also restyle the textarea resizer in WebKit...

Discussion

  1. Actually, Sizzle offers a slight improvement with Firefox 3. i just ran the test a couple of times with the same results – however sizzle comes out with 1 error on a fairly complex selector (“p:nth-child(n)[class] > a”). The actual difference is 204 vs 219 which isn’t much of a difference.

    However Safari 3.2.1 seems to be 20ms faster (50 vs 30) with MooTools. I would however agree that control over the code base is an advantage, but I’m sure Resig evaluated this as well. His blog actually states his thoughts about changing.

  2. After all the speed improvement compared to the latest engine changes in all browsers (= the advent of new javascript engines) is below a ms on a -really- slow computer (I tested it and the computer here at work is six years old). There is absolutely no advantage to use Sizzle in MooTools. It is more code than the “native” MooTools extension and you lose the pseudoselector flexibility.

  3. Agreed 100% Chris.

  4. Most browsers still don’t have a JIT compiler, so the improvements are “temporary” (they will become more insignifigant).
    I don’t use MooTools, but I don’t see how the pseudo-selector support is lost? I use them with no problems in jQuery 1.3. I find the look and feel of animations and the overall framework ease-of-use to be a stronger selling point.

  5. I don’t think I mentioned it directly, but I do agree with you, Chris. Changing the selector engine in MooTools wouldn’t be much an improvement if any. jQuery on the other hand, actually got quite some improvement with it.

  6. Umm… your performance numbers are horribly out of date (over 2 months, at this point). In fact, Sizzle is now over two times faster than MooTools (as of jQuery 1.3). In fact, it looks like Sizzle is going to become another 15-25% faster in the release corresponding with jQuery 1.3.2.

    There’s a full thread discussing this over on Hacker News, where I address this point and more (concerning the integration).

  7. Thank you for bringing the speed improvements to my attention. As I’m sure you noted, I’m simply linking to the MooTools blog’s Slickspeed. Do you have an alternate Slickspeed link available?

    I mean no offense with this post — in fact, I showed users how to make the choice themselves.

  8. @david: No harm felt! Just wanted to clear up any misconceptions. A full breakdown of the methodology, the tests used, and the resulting data can be found in the jQuery 1.3 Performance notes.

  9. John, if you’re comparing jQuery to MooTools, then I can see why MooTools results 2x slower. However, its got nothing to do with selector engines themselves.

    http://mootools.net/same_mootools_vs_latest_sizzle/

    As you can see, MooTools selector engine is still faster than the latest, non-horribly outdated sizzle (0.9.3, from 3 days ago). Also, Sizzle is miserably slow for some selectors, in Firefox 2.

  10. John, seriously, there is no performance advantage when using Sizzle as a Selector Engine in MooTools, it is like you have no idea what you are talking about at all here. The pure Selector Engine in MooTools is as fast as Sizzle in Firefox 3.1b2 as I stated above – both are using querySelector anyway. So a Selector Engine will soon only become something optional that you include if you need to support those legacy browsers, it is nothing that we will even discuss in two year’s time.

    The performance overhead in MooTools is coming from the way MooTools works as it has to post-process every node, you may have read about that some time ago on the MooTools Blog, remember? ;)

    Anyway, what is this bitching of a 3ms advantage all about? It won’t matter at all in browsers aside from IE6 as they all experience a performance gain through engine improvements (TraceMonkey, Squirrelfish, New Opera Engine). The same thing with caching. You have to erase the cache when the DOM changes (which happens very often) and also there is clearly no need to run a selector query on an unchanged DOM-Tree as you can just store the results of your last query in your class/a variable or even globally.

    If you disable caching in Sizzle, don’t have querySelector API available and add the performance overhead that MooTools needs to extend Elements – which is basically what you get with Internet Explorer – then yes, Sizzle is faster. It is like measuring someone with running shoes compared to someone running with iron boots borrowed from Zelda. Doesn’t make sense.

  11. Actually, Chris, the SlickSpeed test is done without extending the elements.

    I cannot agree or disagree with Resig since I don’t know what version the linked page uses. But from the jQuery performance tests it shows a comparison of jQuery and MooTools, not just the selectors. From my own tests done yesterday it seemed pointless for MooTools to change, but if those tests are outdated, my point obviously weakens.

    In any case it’s more relevant to compare the frameworks themselves not just parts of them as Chris rightfully argues. And I still root for jQuery :-)

  12. @Chris: A couple points. Nearly all of the current browsers (Firefox 2, Firefox 3, IE 6, IE 7, and Opera 9.6) DON’T support querySelectorAll. For this reason (considering that this is ~95% of all current browsers) you need to make sure that you selector engine is fast in those browsers. Sizzle happens to do really well in Internet Explorer – and this shows.

    “The performance overhead in MooTools is coming from the way MooTools works as it has to post-process every node, you may have read about that some time ago on the MooTools Blog, remember? ;)”

    Yes. This is why I compared jQuery vs. MooTools in my results (since jQuery has overhead of injecting the returned set of elements into the jQuery object) not Sizzle vs. MooTools.

    “You have to erase the cache when the DOM changes”

    It doesn’t sound like you read the thread that I linked to above. I definitely recommend that you read it – all of these points were already covered. The short story: Sizzle no longer caches queries – the numbers you are seeing are straight querying vs. querying.

    So, in short: querySelectorAll doesn’t exist in the majority of current browsers (thus we don’t get the benefit), there is no query caching currently in Sizzle, and Sizzle has been shown to be provably faster when integrated into another library (not just standalone).

    I also recommend taking a look at the performance results shown above – especially where I describe the methodology. Constructing a good test suite for measuring is just as important as implementing the actual code itself.

    “you lose the pseudoselector flexibility.”

    That’s not true, at all. Sizzle is the most extensible selector engine available today. That was a big trade-off that I made in its construction – I wanted to make sure that all the extensibility could still be provided without sacrificing any performance. The end result? A faster engine that is incredibly extensible – even more so than what’s currently in MooTools.

  13. @john,

    1) MooTools 1.2.1 Selector Engine vs Sizzle 0.9.3 Selector Engine

    Doesnt look to me like its 2x faster.

    This is why I compared jQuery vs. MooTools in my results

    However, you expressly said:

    Sizzle is now over two times faster than MooTools

    This is a test page I prepared with the latest sizzle, and the same mootools selector engine with no overheads, so its really comparing engines performance with no overheads. 2x faster ? run the page and find out…

    Sizzle is the most extensible selector engine available today

    Before doing a comment like this, you should probably take a look at what MooTools lets you customize in selectors. You’d be surprised.

  14. @Valerio: “However, its got nothing to do with selector engines themselves.” It has everything to do with the selector engines. jQuery is using Sizzle – there is not other selector solution in jQuery.

    I see you’ve replied to some of my points over on the Clientcide post regarding this – so I’ll continue the discussion over there.

  15. @Valerio: It seems like some of your messages are being held in moderation, which is creating a weird discussion.

    As I stated quite a few times now: Sizzle is optimized for the selectors that developers actually use – on pages that developers actually develop. In our tests of those selectors on those pages, jQuery (using Sizzle) is over 2x faster than MooTools. See the jQuery 1.3 Performance Notes that I linked to above for more information on the methodology that we use.

    “Before doing a comment like this, you should probably take a look at what MooTools lets you customize in selectors.”

    I have. For example – let’s say you wanted to add a new type of filter, one that allows you to go against CSS attributes, using a syntax like: “div{color=red}”. You can’t do that in the MooTools selector engine without monkey-patching filter and parseSelector methods – but this is something that can be easily plugged in to Sizzle.

  16. I hope I’m allowed to post an article of my Portfolio: PseudoSelectors: extended which shows how easy it is to add custom selectors. Why would I want to add a new syntax with curly braces if a perfect base is already there? :name(property) is all you will ever need.

  17. @Chris: I like your demo – definitely a compelling extension. Valerio was looking for an example of something that couldn’t be done with the MooTools selector engine – so I showed him one example. The syntax may not be to your liking but the fact remains. (If it can be done, I’d love to be corrected – but I don’t see an obvious way to make the extension.)

  18. @John: Your example is compelling–but I have to ask, “What?!”

    The syntax may not be to your liking but the fact remains.

    This statement is too weird. What fact? That Mootools can’t implement something that looks so… uh, I dunno.. “unnatural”?

    So what if Mootools can’t do a “div{color=red}”? As Chris showed us, it’s fully capable of doing a “div:color(red)”–which I assume is exactly the same thing, but somehow looks more like native selectors and, in my vote, is certainly more appealing syntax-wise.

    Please remember that syntax has nothing to do with how extensible Mootools or Sizzle is. Suppose the Mootools team decides to allow something like “div:c:o:l:o:r:{&r&e&d}” which has the same capabilities as your example (God I hope not). Would it be justifiable if Val told you that Mootools is more extensible than Sizzle just because it can do that, even if “the syntax may not be to your liking”? I don’t think so.

    Don’t pass judgement solely on syntax, because whatever syntax the engine uses, it’s whether or not it could correctly parse the DOM that matters. And Mootools has already shown that–it just so happens that Mootools prefers code that actually looks good.

    So let’s get back on what really matters: whether or not Sizzle really outperforms Mootools.

  19. @Mark: Performance is only one piece of the puzzle. You can have awesome performance if you sacrifice extensibility – which is, obviously, something that neither jQuery nor MooTools wishes to do.

    Again, you’re getting way too caught up in the particular example. Just to give some examples of the type of selectors that we’ve been discussing as possible plugins since we have an extensible engine.

    “div < a” – Find all divs that are a parent of an anchor.
    “a & b” – Find all anchors and bold words – but only if they both exist.
    “#foo*” – Find all elements that have an ID that begins with foo.
    “div{color*=red}” – Find all divs whose style color property contains the color red.

    Obviously there is some disagreement as to if adding in new selectors is useful – I say that it is (it empowers the user to create the selectors that best suit their use cases). But, again, while MooTools is extensible – it is so for a limited subset of functionality. The extensibility requirements for Prototype, Dojo, YUI, and jQuery was much higher, so Sizzle was written accordingly.

  20. Getting back to the point of the article….”and that is how you implement Sizzle in MooTools IF YOU WISH TO.”

  21. Half of them are not needed in MooTools, apparently MooTools is so powerful we don’t need custom selectors for that. $$('*[id^=foo]') gets all elements with a name starting with foo. CSS3 ftw.

    $$('a').getParent('div') returns an array with the first div parent of all a elements on the page. You could also probably implement the div:color(red) thing with just checking in your custom selector if color contains red and not only equals red (referring to my blog post from above, this is easily possible). I have no idea what you are doing with a & b but we still have Array.filter so we can do $$(‘selector’).filter(fn) to match all needs. So clearly, there is no need for custom selectors, as said. Also, I think adding a custom Syntax doesn’t make it any easier, MooTools sticks with the :name(property) selector so it still looks natural.

    I want to add that it is not a good idea to optimize the selectors the people use but rather to advocate the recommended usage. For example .classname will always be slower than tag.classname, thats a fact and you (as in: the application developer) should optimize the selectors where appropriate. Given the nature of jQuery to appeal to people not knowing a thing about javascript this might not be possible for you, luckily for us MooTools states it is for the “intermediate to advanced developer” only, so we can :)

  22. am I the only one who doesn’t care about a 2ms speed increase on a selector that’s virtually only used in test suites?

    especially because these test suites return a different result every time, sometimes it’s over 20% difference

    seriously, what’s next? “omg, my thingy was 1 nanosecond faster in 1/1 000 000 tests”?

    come on now

  23. @Chris: There’s a difference between “not needed” and “not wanted”. All the examples that I outlined are already possible in Sizzle/jQuery “div:has(a)”, “[id^=foo]”, etc. Like I said “The extensibility requirements for Prototype, Dojo, YUI, and jQuery was much higher, so Sizzle was written accordingly.”

    Why should developers be forced to work around limitations in selector engines? Developers should write selectors how they wish and they engines should work to improve. Libraries are there for the user and should implement what the users want – not the other way around.

    As to your statement: “For example .classname will always be slower than tag.classname, thats a fact.” Maybe that’s the case in MooTools, but it’s not the case in Sizzle/jQuery. In Firefox 3, Safari, and Opera – which all implement getElementsByClassName – it is faster to just do “.classname” than to do “tag.classname” (since it requires extra post-processing).

  24. @seutje: The issue of minor performance enhancements was not the point so yes: 1 ms here and there isn’t the focus. If you refer to the jQuery test that John made you would see it’s not that close a call after all.
    I retire my original comment due to accusations on the version of the Sizzle version used in the test. As you see, the test was deemed outdated.

    As to the actual flexibility of the codebases I cannot give any thorough comments. But arguing about hypothetical features can only lead to hypothetical results. We usually don’t know what’s next.

  25. @John:

    Again, you’re getting way too caught up in the particular example.

    How could I not? It’s the only one you gave? Besides, my college debate professor always told us that you always go for the kill with your first shot–so I assumed you we’re trying to go for the kill with that one.. I was wrong, I guess.. :P

    Anyway……

    Developers should write selectors how they wish and they engines should work to improve. Libraries are there for the user and should implement what the users want – not the other way around.

    I agree completely. And I think the Mootools devs do too, which is why they gave us, the users, the power to do something like this: http://paste.mootools.net/f5a08747c (Thanks to Simo [worrcu] from #mootools for this one).

    What’s that? It’s an implementation of the “<” selector. Yes, one of the examples you gave. It’s incomplete, since it was just written in the span of a few minutes in between volleys in this thread, but it’s fully functional.

    So what does this mean? In terms of extensibility of selectors, Mootools is at par with JQuery/Sizzle–those examples can be implemented in Mootools just as they can in Jquery/Sizzle. Of course, you could show us a real example of something Mootools can’t do (no syntax issues please.. :P ), but within the unix timestamp of this reply, Mootools and Sizzle/JQuery is even.

    Now, one might argue that the example is too complex. “A regular user can’t do that!” But of course! We have to remember that these things–whether it’s a good thing or not–is not within the grasp of regular devs. It will be the intermediate and advance devs that will do these stuff, and they are the ones who actually know how to do it. I don’t know about you guys, but when I started using Mootools, I never had the urge to say, “Gee Golly Wiz! I do wish I could implement a new selector!” (I honestly don’t sound like that in real life..)

    And for that matter, if you’re an intermediate or advance dev who’s been using Mootools for quite some time, you’ll probably know just how to do these stuff–because you’re already thinking the mootoolsian way.. :)

    But–and this is the biggie–if extending Sizzle is way easier than this (and by way easier I mean that someone who’s a total noob can do it without banging their head on the table and praying to the Gods of Firebug), then I’ll zip it and have my peace.. :D

  26. Don’t trust benchmarks, especially an unmodified Slickspeed.

    What many seems to forget when using it, is that it only runs the query once. On a fast computer that almost always gives a 0 ms result. That doesn’t mean it’s instant, only that it took less that 1 ms. The problem is that timing in JavaScript is limited to milliseconds. So to get a true measurement the query must be run so many times that the total time takes a few ms, then divide the time by iteration count.

    When testing our selector we use a modified Slickspeed. The results are quite interesting.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!