Qwery vs Sizzle

JavaScript performance comparison

Test case created and last updated

Info

Checking perf for basic selectors. Each revision will contain different tests.

Preparation code

<script src="//github.com/dperini/nwmatcher/raw/master/src/nwmatcher.js"></script>
<script src="//github.com/jquery/sizzle/raw/master/sizzle.js"></script>
<script src="//github.com/ded/qwery/raw/master/qwery.js"></script>
<div foo="bar"></div>
<div class="a"></div>
<div id="boosh">
  <div class="a b">
    <div class="d e" test="fg" id="booshTest"></div>
    <em test="f g"></em>
    <span class="h i a"></span>
  </div>
</div>
<div id="attr-test1"></div>
<div id="attr-test2"></div>
<div id="attr-test3" class="found you" title="whatup duders"></div>
<script>
  Benchmark.count = 0;
  Benchmark.prototype.setup = function() {
   var N = NW.Dom.select,
       Q = qwery,
       S = Sizzle,
       c = 0,
       id = "boosh" + (Benchmark.count += this.count),
       el = document.getElementById('boosh');
  };
 
  Benchmark.prototype.teardown = function() {
   el.id = 'boosh';
  };
</script>

Preparation code output

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Qwery div
el.id = id + (++c);
Q('div, #' + id + c);
pending…
Sizzle div
el.id = id + (++c);
S('div, #' + id + c);
pending…
NWMatcher div
el.id = id + (++c);
N('div, #' + id + c);
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

5 comments

John-David Dalton commented :

As of April 1st 2011, Qwery has the following bugs that give a false impression of higher performance:

  • returns a nodeList, and not an array, with tagName selectors like qwery("div") when querySelectorAll isn't supported
  • returns [null], instead of [], for unmatched ID selectors like qwery("#notfound")
  • doesn't match descendants by ID if context is not document like qwery("#found", someElement)
  • doesn't validate or allow escaped values in ID/classNames for browsers that don't use querySelectorAll
  • doesn't check for buggy attribute selectors in IE8/Opera 10
  • doesn't return elements in source order for browsers that don't use getElementsByClassName for selectors like qwery(".a")
  • doesn't return elements in source order for browsers that don't use querySelectorAll for comma separated selectors like qwery("body, html")
  • doesn't remove duplicate elements for browsers that don't use querySelectorAll for comma separated selectors

Dustin Diaz commented :

Fixed a number of these:

  • returns a nodeList, and not an array √
  • returns [null], instead of []
  • doesn't match descendants by ID if context is not document √
  • doesn't remove duplicate elements √

as for the rest...

  • "doesn't return elements in source order for browsers" not necessarily a concern of ours considering there's never been a real-world usecase for it. unless a compelling reasons arrises then we could possibly reverse our for loops to ++ instead of --

  • "doesn't check for buggy attribute selectors in IE8/Opera 10" what are these buggy attribute selectors?

  • "doesn't validate or allow escaped values in ID/classNames" examples? it should be easy to fix with some sample input.

cheers, Dustin

John-David Dalton commented :

  1. "* doesn't match descendants by ID if context is not document √"

    hasn't been fixed.

  2. "Not necessarily a concern of ours considering there's never been a
    real-world usecase for it. unless a compelling reasons arrises then
    we could possibly reverse our for loops to ++ instead of --"

    Cross browser consistency, expecting elements in a certain and consistent order, seems pretty critical and is outlined-in-spec.

  3. "What are these buggy attribute selectors?"

    IE fails in reading:

    • original values for input/textarea
    • 6/7 have problems reading relative paths from href and other URIs
    • original boolean values for controls (attributes like checked, disabled, ismap, multiple, readonly, selected, value)

    IE8 + Opera 10 bug on ^=, $=, & *= operators with empty, "", values

  4. "It should be easy to fix with some sample input."

    For examples an ID may be written as "#B\&W\?" or "#B\26 W\3F"

David Mark commented :

IE fails in reading: original values for input/textarea

The defaultValue property. And no doubt checked (defaultChecked property), selected (defaultSelected property) for the same reason. IE5/6/7/compat mode mix up attributes and properties. Can't use the value, checked or selected properties.

6/7 have problems reading relative paths from href and other URIs

Yes, 5/6/7/compat mode. Again, they are reading the (fully resolved) href, src, longDesc, etc. properties. Same broken-by-design issue (reading property values instead of attribute values).

original boolean values for controls (attributes like checked, disabled, ismap, multiple, readonly, selected, value)

You covered value, checked and selected. It's not just because the latter two are booleans. They are properties that reflect user input, so you have to check the default* properties to determine the "original" values. But disabled, multiple, ismap, etc. must be treated differently only because they are booleans (they do not reflect user input). It's the property/attribute mixup again.

Most query engines don't account for this problem (or account for just part of it), despite the fact that it's been around since 1999. For example, they may come up with false for the checked attribute through type conversion (boolean to string) and the query engine takes it as a positive result for that attribute (because it found some non-empty string). The possibilities are mind-boggling and best avoided.

http://www.cinsoft.net/attributes.html

David Mark commented :

Oh, and I should mention that Sizzle is squarely in that "most" category too. That script doesn't handle the IE attribute problems. It doesn't even try.

Looks like the performance clash was a push anyway. :)

Add a comment