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
Last visit > 30 days ago
Closed: Apr 2014
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 2
Type: Bug

issue 351146

Sign in to add a comment
Creating a polymer element with empty <style> appears n^2
Project Member Reported by, Mar 10 2014 Back to list
Google Chrome	35.0.1880.0 (Official Build 255773) canary
OS	Mac OS X 
Blink	537.36 (@168755)

<polymer-element name="cr-toolbar" noscript>

t =; var d = document.createElement('div'); document.body.appendChild(d); for (var i = 0; i < 5000; ++i) d.appendChild(document.createElement("cr-toolbar")).textContent = "foo" + i; console.log( - t);
4633.758999989368 VM101103:2

t =; var d = document.createElement('div'); document.body.appendChild(d); for (var i = 0; i < 5000; ++i) d.appendChild(document.createElement("cr-toolbar")).textContent = "foo" + i; console.log( - t);
11927.791999973124 VM101106:2

t =; var d = document.createElement('div'); document.body.appendChild(d); for (var i = 0; i < 5000; ++i) d.appendChild(document.createElement("cr-toolbar")).textContent = "foo" + i; console.log( - t);

Each time you run this benchmark it gets worse and worse.
There's still a bug here with the number of tree scopes causing progressive slowdown, but the massive hit seems to be related to the web inspector being open. If I close the web inspector I get radically different numbers:


Blockedon: chromium:350797
Blockedon: -chromium:350797
Pleas use jsperf for performance metrics. It is easier to iterate against the list with the perf test that way. I'm removing the blocked on since it is a poor excuse for not iterating on the slow down mentioned in comment#1.

Style-related slow dows in inspector is already tracked as
 Issue 351118  has been merged into this issue.
StyleSheetContents::checkLoaded appears to be the culprit, attached is a trace of the test case from  issue 351118  (by sorvell)

Running Time	Self		Symbol Name
3261.0ms  100.0%	1.0	 	WebCore::Node::appendChild(WTF::PassRefPtr<WebCore::Node>, WebCore::ExceptionState&)
3257.0ms   99.8%	3.0	 	 WebCore::ContainerNode::appendChild(WTF::PassRefPtr<WebCore::Node>, WebCore::ExceptionState&)
3252.0ms   99.7%	4.0	 	  WebCore::ContainerNode::updateTreeAfterInsertion(WebCore::Node&)
3227.0ms   98.9%	3.0	 	   WebCore::ChildNodeInsertionNotifier::notify(WebCore::Node&)
3146.0ms   96.4%	0.0	 	    WebCore::HTMLStyleElement::didNotifySubtreeInsertionsToDocument()
3145.0ms   96.4%	8.0	 	     WebCore::StyleElement::processStyleSheet(WebCore::Document&, WebCore::Element*)
3033.0ms   93.0%	4.0	 	      WebCore::StyleElement::createSheet(WebCore::Element*, WTF::String const&)
2945.0ms   90.3%	2588.0	 	       WebCore::StyleSheetContents::checkLoaded()
176.0ms    5.3%	176.0	 	        WTF::Vector<WebCore::CSSStyleSheet*, 0ul, WTF::DefaultAllocator>::Vector(WTF::Vector<WebCore::CSSStyleSheet*, 0ul, WTF::DefaultAllocator> const&)
172.0ms    5.2%	2.0	 	        WebCore::CSSStyleSheet::sheetLoaded()
7.0ms    0.2%	2.0	 	        WTF::partitionFreeSlowPath(WTF::PartitionPage*)
2.0ms    0.0%	2.0	 	        WebCore::HTMLStyleElement::notifyLoadedSheetAndAllCriticalSubresources(bool)
27.0ms    0.8%	1.0	 	       WebCore::MediaQueryEvaluator::MediaQueryEvaluator(char const*, bool)
21.0ms    0.6%	6.0	 	       WebCore::StyleEngine::createSheet(WebCore::Element*, WTF::String const&, WTF::TextPosition, bool)
19.0ms    0.5%	2.0	 	       WebCore::ContentSecurityPolicy::allowStyleHash(WTF::String const&) const
10.0ms    0.3%	0.0	 	       <Unknown Address>
2.0ms    0.0%	1.0	 	       non-virtual thunk to WebCore::HTMLStyleElement::type() const
1.0ms    0.0%	1.0	 	       WebCore::ContentSecurityPolicy::allowStyleNonce(WTF::String const&) const
1.0ms    0.0%	1.0	 	       WebCore::MediaQuerySet::create(WTF::String const&)
1.0ms    0.0%	1.0	 	       non-virtual thunk to WebCore::HTMLStyleElement::media() const
1.0ms    0.0%	1.0	 	       DYLD-STUB$$WTF::fastMalloc(unsigned long)
1.0ms    0.0%	0.0	 	       WebCore::CSSStyleSheet::setMediaQueries(WTF::PassRefPtr<WebCore::MediaQuerySet>)
88.0ms    2.6%	2.0	 	      WebCore::StyleEngine::addStyleSheetCandidateNode(WebCore::Node*, bool)

Specifically it appears that the issue is that it's iterating all the clients:

Vector<CSSStyleSheet*> clients(root->m_clients);
    for (unsigned i = 0; i < clients.size(); ++i) {
        // Avoid |CSSSStyleSheet| and |ownerNode| being deleted by scripts that run via
        // ScriptableDocumentParser::executeScriptsWaitingForResources().
        RefPtr<CSSStyleSheet> protectClient(clients[i]);

        if (clients[i]->loadCompleted())

        // sheetLoaded might be invoked after its owner node is removed from document.
        if (RefPtr<Node> ownerNode = clients[i]->ownerNode()) {
            if (clients[i]->sheetLoaded())

which is n^2 since each <style> is calling checkLoaded(), and all of them have loaded already, so we keep going through the list over and over again noticing that there's no work to do.

This is probably why the stylesheet caching seems to not be working very well. Once you have lots of sharing this loop starts to beat down on your app.

1.5 KB View Download
Status: Available
Labels: hotlist-toolkit
 Issue 351118  has been merged into this issue.
Blocking: chromium:351146
 Issue 351118  has been merged into this issue.
There is a similar n^2 when the inspector is up. It needs to know which stylesheets come and go. So if this gets resolved, it'd be great to have a way for inspector to hook in and not re-do this work.
Comment 12 by, Mar 11 2014
Based on the profile mostly lighting up in Vector, this is partly a regression from (though I'd have to compare to the behavior with that patch reverted to see what the performance would be like)
Comment 13 by, Mar 12 2014
Status: Started
I'll take a stab at this. My changes made this worse, but it should be fairly easy to keep track of which CSSStyleSheets are loaded and which are not so we only iterate the interesting ones. My change makes that simpler because I'm now using HashSets.
Project Member Comment 14 by, Mar 14 2014
The following revision refers to this bug:

r169287 | | 2014-03-14T23:32:38.243508Z

Changed paths:

Optimize StyleSheetContents::checkLoaded by keeping track of completed
and loading clients.

For the input-wstyle.html benchmark from the bug report this brings
the difference between the x-input and the x-input-style down to
a factor of two and the time scales linearly with the number of
elements added in the benchmark.

x-input: 52.1520ms
x-input-style: 105.3900ms
input: 27.0840ms,,,
BUG= 350785 

Review URL:
Comment 15 by, Apr 1 2014
Status: Fixed
Sign in to add a comment