WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
Bug 36303
Inserting CSS rules one at a time via js causes slow synchronous style recalculation
https://bugs.webkit.org/show_bug.cgi?id=36303
Summary
Inserting CSS rules one at a time via js causes slow synchronous style recalc...
Tom Stanis
Reported
2010-03-18 10:49:41 PDT
Created
attachment 51049
[details]
HTML page illustrating the bug Using sheet.insertRule() causes webkit to re-evaluate all of the style rules synchronously. This means that if you have a bunch of rules that are added one at a time, styles will be recalculated multiple times. Instead, we should start the relayout timer and evaluate all of these styles once. Attached is an HTML page that clearly illustrates how slow this can be. In my tests this takes ~3000ms whereas firefox completes much quicker. I have a fix in progress that brings this down to ~100ms.
Attachments
HTML page illustrating the bug
(68.33 KB, text/html)
2010-03-18 10:49 PDT
,
Tom Stanis
no flags
Details
patch to fix bug
(3.60 KB, patch)
2010-03-18 17:23 PDT
,
Tom Stanis
no flags
Details
Formatted Diff
Diff
Patch
(19.31 KB, patch)
2010-08-25 17:30 PDT
,
Dave Hyatt
hyatt
: review-
Details
Formatted Diff
Diff
Patch
(19.54 KB, patch)
2010-08-26 10:41 PDT
,
Dave Hyatt
simon.fraser
: review+
Details
Formatted Diff
Diff
Show Obsolete
(2)
View All
Add attachment
proposed patch, testcase, etc.
Tom Stanis
Comment 1
2010-03-18 17:23:06 PDT
Created
attachment 51113
[details]
patch to fix bug Still trying to wok through some test failures, but this patch solves the performance problem.
James Robinson
Comment 2
2010-03-18 17:47:13 PDT
+cc'ing a few folks. FYI, this bug has hit a lot of Google properties and likely lots of other pages on the web. Looks like a good patch to me (but I am not a reviewer). Style nit: one-line blocks do not get curly braces.
mitz
Comment 3
2010-03-18 17:56:02 PDT
The tricky part is that attach() requires the style selector to be up to date, but by the time attach() is entered, it is too late to update the style selector and recalcStyle() for the entire document.
James Robinson
Comment 4
2010-03-18 18:30:21 PDT
Could we just defer all the work in attach() until the next recalcStyle()? From a quick glance, the only work in attach() that depends on the style selector is mutating the render tree and it should be fine for the render tree to be stale as long as it's updated before entering layout().
James Robinson
Comment 5
2010-03-19 15:13:04 PDT
Or to put it another way, why not always force the Node::lazyAttach() case. I'm experimenting with this locally and it seems to not be too bad. The tricky cases are plugins and shadow DOM trees. Plugins are tricky because they are instantiated through a RenderWidget and need to start up synchronously, but it should be pretty simple to force a layout pass after adding them to the DOM. Shadow DOM trees can be lazily created, there's no reason for them to even exist until layout will occur. There are a few more corner cases but they don't seem too tricky. Is there any reason why this can't work?
Dave Hyatt
Comment 6
2010-05-19 14:15:09 PDT
Comment on
attachment 51113
[details]
patch to fix bug You should inline updateStyleSelectorIfDirty. It's silly to do two function calls when most of the time you won't be dirty.
Dave Hyatt
Comment 7
2010-05-19 14:16:20 PDT
Comment on
attachment 51113
[details]
patch to fix bug You should inline updateStyleSelectorIfDirty. It's silly to do two function calls when most of the time you won't be dirty.
Dave Hyatt
Comment 8
2010-05-19 14:18:36 PDT
Also, lots of extra { } in if statements that should be removed. Also, the placement of updateStyleSelectorIfDirty is bad. It should happen before the recalcStyle, and the recalcStyle should not happen if the updateStyleSelector ran. You should make a new helper function that combines the updateStyleSelector check with this code: // Always ensure our style info is up-to-date. This can happen in situations where // the layout beats any sort of style recalc update that needs to occur. if (m_frame->needsReapplyStyles()) m_frame->reapplyStyles(); else if (document->childNeedsStyleRecalc()) document->recalcStyle(); The logic should be something like: if (m_styleSelectorDirty) updateStyleSelector(); else if (m_frame->needsReapplyStyles()) etc.
Dave Hyatt
Comment 9
2010-05-19 14:36:10 PDT
I think you could keep chugging along by using styleNotYetAvailable stuff... the same thing we do when stylesheets haven't loaded. The new objects would get parsed and attached but have no renderers. Eventually you'd yield back to the run loop and the layout would happen, and you'd get the renderers made. Note that you also need to patch the recalc style timer to update the style selector if needed. We don't want that firing and not updating the style selector first.
mitz
Comment 10
2010-05-25 15:13:33 PDT
See also
bug 39647
.
Dave Hyatt
Comment 11
2010-08-25 17:30:53 PDT
Created
attachment 65505
[details]
Patch
Simon Fraser (smfr)
Comment 12
2010-08-25 17:34:10 PDT
Comment on
attachment 65505
[details]
Patch
> Index: WebCore/rendering/RenderBlock.cpp > =================================================================== > --- WebCore/rendering/RenderBlock.cpp (revision 66057) > +++ WebCore/rendering/RenderBlock.cpp (working copy) > @@ -4132,8 +4132,7 @@ void RenderBlock::setDesiredColumnCountA > bool destroyColumns = !firstChild() > || (count == 1 && style()->hasAutoColumnWidth()) > || firstChild()->isAnonymousColumnsBlock() > - || firstChild()->isAnonymousColumnSpanBlock() > - || document()->settings()->paginateDuringLayoutEnabled(); > + || firstChild()->isAnonymousColumnSpanBlock();
Unrelated change here. I like it! r=me
James Robinson
Comment 13
2010-08-25 17:38:17 PDT
Awesome! What still calls Document::updateStyleSelector()?
Early Warning System Bot
Comment 14
2010-08-25 17:54:50 PDT
Attachment 65505
[details]
did not build on qt: Build output:
http://queues.webkit.org/results/3731592
Dave Hyatt
Comment 15
2010-08-25 18:14:20 PDT
Comment on
attachment 65505
[details]
Patch Ran across a doctype bug in the Html5 parser that I have to fix.
Eric Seidel (no email)
Comment 16
2010-08-25 23:31:12 PDT
Oh, do tell! :)
Dimitri Glazkov (Google)
Comment 17
2010-08-26 07:16:39 PDT
This looks great!
Dave Hyatt
Comment 18
2010-08-26 10:41:53 PDT
Created
attachment 65578
[details]
Patch This patch fixes the bug. One layout test changes results to be incorrect, but it's an artifact of a later style recalc happening after the HTML5 parser altered the document to be in quirks mode without doing a style recalc of its own. The timer-based one then fixes the document up. After I land this patch, I'm going to do a big doctype/quirks mode cleanup now that I have discovered this issue.
Early Warning System Bot
Comment 19
2010-08-26 11:05:46 PDT
Attachment 65578
[details]
did not build on qt: Build output:
http://queues.webkit.org/results/3761660
Dave Hyatt
Comment 20
2010-08-26 11:20:56 PDT
Fixed in
r66115
.
WebKit Review Bot
Comment 21
2010-08-26 11:32:31 PDT
http://trac.webkit.org/changeset/66115
might have broken Qt Linux ARMv5 Release
Tony Chang
Comment 22
2010-08-27 18:36:46 PDT
This seems to have caused a perf regression in the chromium intl1 page cycler. I filed
bug 44808
about this and added a test case there.
Tony Chang
Comment 23
2010-09-01 12:38:08 PDT
(In reply to
comment #22
)
> This seems to have caused a perf regression in the chromium intl1 page cycler. I filed
bug 44808
about this and added a test case there.
Are we ok with taking the perf regression from this change mentioned in
bug 44808
? If so, should I just close that bug? It seems like this change made some cases faster and some cases slower.
David Kilzer (:ddkilzer)
Comment 24
2010-10-06 12:27:29 PDT
<
rdar://problem/8302217
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug