The RuleProcessorData constructor pretty routinely shows up in profiles as a few % of total time. For profiles of things like querySelector or frame construction it can be closer to 10%.
The fundamental design assumption with RuleProcessorData is that a single element is compared to a bunch of selectors, so that it makes sense to pre-grab all sorts of information about the element and then have fast access to it.
But in practice, not all RuleProcessorDatas are created equal. The querySelector ones only ever get compared to one selector. The ones created by the LHS selector of various combinators might not be compared to as many selectors as the RHS.
I did some measuring (excluding XUL elements for now due to bug 523047, but I should consider measuring even with those rules in), and after a bit of gmailing I have some data in histogram form (sadly the histogram bar sizes seem to be the log_2 of the number, not the number itself). "RHS selectors" refers to rule processor data that was not created due to needing to test an ancestor or prev sibling due to a combinator. "LHS" selectors" refers to data created due to combinators. "Matches against ___ selectors" are the number of SelectorMatches calls for data of that type. "Matches against non-tag ___ selectors" are numbers of such calls that make it past the tag/namespace check up front. "Matches against non-tag non-class non-id ___ selectors" are numbers of such calls that make it past the tag, class, and id checks (I moved the class and id checks earlier in SelectorMatches).
Summary: for the "LHS" case, 88% of the RuleProcessorData only need tag/namespace/id/class to not match and 95% are only matched against one selector that includes anything other than tag/namespace/id/class. If I only look at tag/namespace, then the numbers are 2 and 11% respectively. For the "RHS" case, the tag/namespace/id/class numbers are 70% and 71% respectively. The tag/namespace numbers are 26% and 50%. Note that in general there are 3x as many "LHS" SelectorMatches calls as there are "RHS" ones on gmail.
I'm going to try to get some numbers from our Tp set as well, but at first glance it looks like at least for LHS selectors we should consider lazy-initializing everything other than tag/namespace/id/class. For RHS selectors it might even be worth lazy-initializing id/class, since a quarter of the selectors don't need even those, and they aren't that cheap to initialize...
> I'm going to try to get some numbers from our Tp set as well
tp for non-XUL nodes histograms are below. Summary: For the "LHS" case, 80% of RuleProcessorData only need tag/namespace/id/class to not match. Anothe 12% are only matched against one selector after matching on tag/namespace/id/class.
For the "RHS" case, the numbers are 72% and 73% respectively. For the RHS case, also, just the tag+namespace accounts for a pretty high proportion of non-matches (60%).
There are 2.25 times as many "LHS" datas as "RHS" ones.
Since RHS datas always need the tag/id/classes due to ContentEnumFunc needing that information, I propose we stick to eagerly getting those in the RuleProcessorData ctor for now but switch to lazily getting mIsLink/mLinkState and mEventState. Will file a bug on this.