Project: chromium Issues People Development process History Sign in
New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.
Starred by 2 users
Status: Fixed
Owner:
Closed: Mar 2014
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 2
Type: Bug

Blocking:
issue 351146



Sign in to add a comment
Rule matching in ShadowRoot is too slow with complex sheets
Project Member Reported by esprehn@chromium.org, Mar 11 2014 Back to list
Google Chrome	35.0.1870.2 (Official Build 254650) dev
OS	Mac OS X 
Blink	537.36 (@168356)

It seems that rule matching is really expensive inside ShadowRoots, if you include all of bootstrap at the top of the document and append 5000 divs and 5000 x-customs time measured by the benchmark is around 260ms, if you put the stylesheet into the components the rule matching jumps up to 3200ms.

Running Time	Self		Symbol Name
1642.0ms   10.6%	1642.0	 	WebCore::ElementRuleCollector::ruleMatches(WebCore::RuleData const&, WebCore::ContainerNode const*, WebCore::SelectorChecker::BehaviorAtBoundary, WebCore::SelectorChecker::MatchResult*)
1546.0ms    9.9%	1546.0	 	bool WebCore::SelectorChecker::checkOne<WebCore::DOMSiblingTraversalStrategy>(WebCore::SelectorChecker::SelectorCheckingContext const&, WebCore::DOMSiblingTraversalStrategy const&, unsigned int*) const
1545.0ms    9.9%	1545.0	 	WTF::CString WTF::TextCodecUTF8::encodeCommon<unsigned char>(unsigned char const*, unsigned long)
1439.0ms    9.2%	1439.0	 	WebCore::anyAttributeMatches(WebCore::Element&, WebCore::CSSSelector::Match, WebCore::CSSSelector const&)
1062.0ms    6.8%	1062.0	 	WebCore::SelectorChecker::SelectorChecker(WebCore::Document&, WebCore::SelectorChecker::Mode)
882.0ms    5.6%	882.0	 	WebCore::ElementRuleCollector::collectRuleIfMatches(WebCore::RuleData const&, WebCore::SelectorChecker::BehaviorAtBoundary, unsigned int, unsigned int, WebCore::MatchRequest const&, WebCore::RuleRange&)
765.0ms    4.9%	765.0	 	WebCore::Node::containsIncludingShadowDOM(WebCore::Node const*) const
492.0ms    3.1%	492.0	 	WebCore::StyleSheetContents::checkLoaded()
453.0ms    2.9%	453.0	 	WebCore::SelectorChecker::Match WebCore::SelectorChecker::match<WebCore::DOMSiblingTraversalStrategy>(WebCore::SelectorChecker::SelectorCheckingContext const&, WebCore::DOMSiblingTraversalStrategy const&, WebCore::SelectorChecker::MatchResult*) const
423.0ms    2.7%	423.0	 	WebCore::Element::synchronizeAttribute(WTF::AtomicString const&) const
377.0ms    2.4%	377.0	 	WebCore::ElementRuleCollector::collectMatchingRules(WebCore::MatchRequest const&, WebCore::RuleRange&, WebCore::SelectorChecker::BehaviorAtBoundary, unsigned int, unsigned int)
325.0ms    2.0%	325.0	 	WebCore::CSSSelector::specificityForOneSelector() const
305.0ms    1.9%	305.0	 	WebCore::RuleData::RuleData(WebCore::StyleRule*, unsigned int, unsigned int, WebCore::AddRuleFlags)
304.0ms    1.9%	304.0	 	WTF::Vector<WebCore::RuleFeature, 0ul, WTF::DefaultAllocator>::expandCapacity(unsigned long)
245.0ms    1.5%	245.0	 	WebCore::RuleFeatureSet::collectFeaturesFromSelector(WebCore::CSSSelector const&, WebCore::RuleFeatureSet::FeatureMetadata&, WebCore::RuleFeatureSet::SelectorFeatureCollectionMode)
240.0ms    1.5%	240.0	 	WebCore::RuleSet::compactPendingRules(WTF::HashMap<WTF::AtomicString, WTF::OwnPtr<WTF::LinkedStack<WebCore::RuleData> >, WTF::AtomicStringHash, WTF::HashTraits<WTF::AtomicString>, WTF::HashTraits<WTF::OwnPtr<WTF::LinkedStack<WebCore::RuleData> > >, WTF::DefaultAllocator>&, WTF::HashMap<WTF::AtomicString, WTF::OwnPtr<WebCore::RuleData>, WTF::AtomicStringHash, WTF::HashTraits<WTF::AtomicString>, WTF::HashTraits<WTF::OwnPtr<WebCore::RuleData> >, WTF::DefaultAllocator>&)
220.0ms    1.4%	220.0	 	WTF::HashTableAddResult<WTF::KeyValuePair<WTF::AtomicString, WTF::RefPtr<WebCore::DescendantInvalidationSet> > > WTF::HashTable<WTF::AtomicString, WTF::KeyValuePair<WTF::AtomicString, WTF::RefPtr<WebCore::DescendantInvalidationSet> >, WTF::KeyValuePairKeyExtractor, WTF::AtomicStringHash, WTF::HashMapValueTraits<WTF::HashTraits<WTF::AtomicString>, WTF::HashTraits<WTF::RefPtr<WebCore::DescendantInvalidationSet> > >, WTF::HashTraits<WTF::AtomicString>, WTF::DefaultAllocator>::add<WTF::HashMapTranslator<WTF::HashMapValueTraits<WTF::HashTraits<WTF::AtomicString>, WTF::HashTraits<WTF::RefPtr<WebCore::DescendantInvalidationSet> > >, WTF::AtomicStringHash>, WTF::AtomicString, WTF::PassRefPtr<WebCore::DescendantInvalidationSet> >(WTF::AtomicString const&, WTF::PassRefPtr<WebCore::DescendantInvalidationSet> const&)
215.0ms    1.3%	215.0	 	WebCore::CSSSelector::extractPseudoType() const
206.0ms    1.3%	206.0	 	WebCore::ScopedStyleTree::setupScopedStylesTree(WebCore::ScopedStyleResolver*)
123.0ms    0.7%	123.0	 	WebCore::RuleFeatureSet::collectFeaturesFromRuleData(WebCore::RuleData const&)
122.0ms    0.7%	122.0	 	WebCore::RuleFeatureSet::add(WebCore::RuleFeatureSet const&)
120.0ms    0.7%	120.0	 	WebCore::CSSSelector::specificity() const
117.0ms    0.7%	117.0	 	WTF::fastMalloc(unsigned long)
113.0ms    0.7%	113.0	 	WebCore::SelectorFilter::collectIdentifierHashes(WebCore::CSSSelector const&, unsigned int*, unsigned int)
95.0ms    0.6%	95.0	 	WTF::fastFree(void*)
80.0ms    0.5%	0.0	 	 WebCore::RuleSet::compactPendingRules(WTF::HashMap<WTF::AtomicString, WTF::OwnPtr<WTF::LinkedStack<WebCore::RuleData> >, WTF::AtomicStringHash, WTF::HashTraits<WTF::AtomicString>, WTF::HashTraits<WTF::OwnPtr<WTF::LinkedStack<WebCore::RuleData> > >, WTF::DefaultAllocator>&, WTF::HashMap<WTF::AtomicString, WTF::OwnPtr<WebCore::RuleData>, WTF::AtomicStringHash, WTF::HashTraits<WTF::AtomicString>, WTF::HashTraits<WTF::OwnPtr<WebCore::RuleData> >, WTF::DefaultAllocator>&)
3.0ms    0.0%	0.0	 	 WTF::ListHashSet<WebCore::TreeScope*, 16ul, WTF::PtrHash<WebCore::TreeScope*> >::remove(WebCore::TreeScope* const&)
3.0ms    0.0%	0.0	 	 WebCore::ElementRuleCollector::~ElementRuleCollector()

Looking at the profile it looks like style sharing is crazy expensive because it's matching tons of fancy selectors over and over again in that last step in SharedStyleFinder. The attribute selector logic also looks really expensive.

Running Time	Self		Symbol Name
4184.0ms   33.6%	1.0	 	                   WebCore::SharedStyleFinder::findSharedStyle()
4150.0ms   33.3%	0.0	 	                    WebCore::ElementRuleCollector::hasAnyMatchingRules(WebCore::RuleSet*)
4124.0ms   33.1%	183.0	 	                     WebCore::ElementRuleCollector::collectMatchingRules(WebCore::MatchRequest const&, WebCore::RuleRange&, WebCore::SelectorChecker::BehaviorAtBoundary, unsigned int, unsigned int)
3941.0ms   31.6%	381.0	 	                      WebCore::ElementRuleCollector::collectRuleIfMatches(WebCore::RuleData const&, WebCore::SelectorChecker::BehaviorAtBoundary, unsigned int, unsigned int, WebCore::MatchRequest const&, WebCore::RuleRange&)
3559.0ms   28.6%	793.0	 	                       WebCore::ElementRuleCollector::ruleMatches(WebCore::RuleData const&, WebCore::ContainerNode const*, WebCore::SelectorChecker::BehaviorAtBoundary, WebCore::SelectorChecker::MatchResult*)
2228.0ms   17.9%	222.0	 	                        WebCore::SelectorChecker::Match WebCore::SelectorChecker::match<WebCore::DOMSiblingTraversalStrategy>(WebCore::SelectorChecker::SelectorCheckingContext const&, WebCore::DOMSiblingTraversalStrategy const&, WebCore::SelectorChecker::MatchResult*) const
2006.0ms   16.1%	743.0	 	                         bool WebCore::SelectorChecker::checkOne<WebCore::DOMSiblingTraversalStrategy>(WebCore::SelectorChecker::SelectorCheckingContext const&, WebCore::DOMSiblingTraversalStrategy const&, unsigned int*) const
1236.0ms    9.9%	973.0	 	                          WebCore::anyAttributeMatches(WebCore::Element&, WebCore::CSSSelector::Match, WebCore::CSSSelector const&)
27.0ms    0.2%	0.0	 	                          <Unknown Address>
538.0ms    4.3%	538.0	 	                        WebCore::SelectorChecker::SelectorChecker(WebCore::Document&, WebCore::SelectorChecker::Mode)
1.0ms    0.0%	0.0	 	                       <Unknown Address>

This is because we keep a global list of sibling and attribute rules inside StyleResolver. While we did share the stylesheet between the elements, we add their sibling and attribute rules n times into the StyleResolver so you have 5000 copies of the bootstrap attribute and sibling selectors in there which makes recalcStyle slow to a crawl.

    OwnPtr<RuleSet> m_siblingRuleSet;
    OwnPtr<RuleSet> m_uncommonAttributeRuleSet;

We should de-duplicate the RuleSets we add to the m_siblingRuleSet and m_uncommonAttributeRuleSet since they might be shared.
 
Comment 1 Deleted
Comment 2 Deleted
Comment 3 Deleted
Comment 4 by adamk@chromium.org, Mar 11 2014
Owner: adamk@chromium.org
Status: Assigned
Project Member Comment 5 by bugdroid1@chromium.org, Mar 12 2014
The following revision refers to this bug:
    http://src.chromium.org/viewvc/blink?view=rev&rev=169044

------------------------------------------------------------------------
r169044 | adamk@chromium.org | 2014-03-12T18:39:40.021741Z

Changed paths:
   M http://src.chromium.org/viewvc/blink/trunk/Source/core/css/resolver/ScopedStyleResolver.h?r1=169044&r2=169043&pathrev=169044
   A http://src.chromium.org/viewvc/blink/trunk/PerformanceTests/ShadowDOM/shadow-style-share-attr-selectors.html?r1=169044&r2=169043&pathrev=169044
   M http://src.chromium.org/viewvc/blink/trunk/Source/core/css/resolver/ScopedStyleTree.cpp?r1=169044&r2=169043&pathrev=169044
   M http://src.chromium.org/viewvc/blink/trunk/Source/core/css/resolver/ScopedStyleResolver.cpp?r1=169044&r2=169043&pathrev=169044

Only process each StyleSheetContents once when collecting features during style resolution

Now that Blink shares StyleSheetContents between <style> elements with
identical textContent, it's wasteful to add features from every
CSSStyleSheet instance.

Instead, keep a HashSet of visited StyleSheetContents in
ScopedStyleTree::collectFeaturesTo() and consult it when adding each
stylesheet's features in ScopedStyleResolve::collectFeaturesTo().

The included test goes from ~390ms on my Z620 without to patch
down to ~80ms with it.

BUG= 351145 

Review URL: https://codereview.chromium.org/195903002
------------------------------------------------------------------------
Comment 6 by adamk@chromium.org, Mar 12 2014
Status: Fixed
Sign in to add a comment