I posted about this on Basecamp, but now that we've started to use this
list I'm going to post it here for public consumption.

We've talked about optimizing $$ in the past -- it's one of my personal
goals for 1.5.1.  So I took great interest in Jack Slocum's new
DomQuery extension for YUI
(http://www.jackslocum.com/blog/2007/01/11/domquery-css-selector-basic-xpath-implementation-with-benchmarks/).
 Jack is a brilliant JavaScripter and has managed to write a really,
really fast CSS selector engine here.

I took a look at his code -- it's quite clever, but also verbose and
inelegant in places.  He handles a lot of specific CSS token
combinations by hand, which results in really fast querying but also
*lots* of lines of code.  I resolved to write a version that was more
Prototypish.

In the middle of doing so, I thought back to my earlier attempt with
XPath
(http://www.andrewdupont.net/2006/07/10/more-than-you-ever-wanted-to-know-about-and-xpath/),
and realized that I could add on an XPath approach with just a bit more
code.  So I did.

You can view the code at
(http://andrewdupont.net/test/double-dollar/selector.new.js). I've set
up a test page (expertly made by the jQuery team) that compares the
speed of the current $$ and my experimental $$:
(http://andrewdupont.net/test/double-dollar/).

I'm still trying to make it better, but as I see it this new $$ solves
several problems with the current $$:

(1) The current $$ does not filter out duplicates.
You can see this on the test page: "div div" and "div div div" both
return far more results than they should because certain nodes are
added to the collection more than once.  Calling "uniq" on the array
before it's returned is *far* too costly, so I used Jack's inspired
method here: it enumerates the collection sets a property on each node,
so that if the function finds a node with that property already it
knows it's seen it before.  (It then sets that property to "undefined"
before it's done.)

(2) The current $$ is not very modular or extensible.
With this new implementation, I can add new tokens very easily -- for
example, all the operators for attribute matching (=, $=, ^=, *=, |=,
~=) -- because they live in a hash with the operator as the key and a
comparator as the value.  Similarly, adding new selectors like child
(>) and adjacency (+), or even pseudoclasses (:nth-child(even)) could
be done by adding a regex, an XPath translation, and a
string-of-JS-code translation.

(3) The current $$ is SLOW.
XPath clearly solves this problem (try the tests in Firefox and see for
yourself), but not for Safari (version <2.0) or MSIE (version
*anything*).  So even the "slow lane" needs to be faster here.  Jack
claims his implementation is the fastest on earth, and though I've
taken his general approach I have not yet realized his gains.  Still,
on costly selectors the new approach is almost twice as fast as the
current $$ (even leaving out XPath), and that's with more functionality
and fewer bugs (i.e., duplicated nodes).


I'd love to hear some feedback.  I've been looking at this code for way
too long now, so a fresh pair of eyes may point out something obvious
that I've missed.  Also, I'd love it if someone were to modify this
code to add new stuff so that $$ can accommodate a wider range of
selectors.

Cheers,
Andrew


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Prototype: Core" group.
To post to this group, send email to [EMAIL PROTECTED]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to