Closed Bug 938139 Opened 11 years ago Closed 11 years ago

:-moz-any selector is too slow

Categories

(Core :: CSS Parsing and Computation, defect, P4)

defect

Tracking

()

RESOLVED INVALID

People

(Reporter: julienw, Unassigned)

References

()

Details

(Keywords: perf)

Reference jsperf testcase: http://jsperf.com/mozany

It seems using ":-moz-any(tag1, tag2)" is slower than using "tag1, tag2".

The testcase does not do exactly this but is closer to a real case I have: I need to match on an attribute for different element names, and I thought that specifying a tag would make this match faster. This is true for usual tag selectors, but not when using :-moz-any to do essentially the same thing.
Component: DOM: Core & HTML → CSS Parsing and Computation
:-moz-any(tag1, tag2) is not quite equivalent as a selector to "tag1, tag2" (e.g. it has a different specificity).  As a result, it can't be desugared to those.

So when we get to SelectorMatches, we check for a namespace (there isn't any), then for a tag selector (there isn't any), then id (none), then class (none), and only after that do we look for a pseudo-class selector.  Thus :-moz-any(tag1, tag2) automatically means a bit more work than using tag names individually.  Furthermore, it involves an extra pair of function calls to check whether the sub-selectors of :-moz-any match.

To put numbers to all this, the testcase has about 3000 elements that get matched against the selector.  Over here I see the -moz-any version running at about 6700 runs/s and the double selector version running at 8200 runs/s.  If I take out the red-herring textContent sets, it's more like 7200 and 8500 respectively.  I have a 2.7Ghz CPU, so that means about 106 CPU cycles per element for the "double selector" case and about 125 CPU cycles per element for the "-moz-any" case.  Given the cost of two extra function costs and some extra branches described above, this is not exactly surprising...

I should also note that for this particular testcase (in which all elements match teh element selectors) "[href]" is in fact the fastest selector of the bunch, since it's the one that has to do the least amount of work.

In any case, the only thing we could maybe do here is actually desugar the -moz-any in the special case of querySelector, but that can also have undesirable performance characteristics in other cases, so I'm not sure it's worth trying to do that.
Keywords: perf
OS: Linux → All
Priority: -- → P4
Hardware: x86_64 → All
Thanks for the good explanation.

I now understand why "[href]" is faster than the other selectors in this case.

Now I don't think any work is needed right now, better wait for the actual usages on the Web. If that's ok to you, let's close this INVALID.
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.