WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
13487
Implement O(1) absoluteClippedOverflowRect and absoluteOutlineBox during layout for a possible speed gain
https://bugs.webkit.org/show_bug.cgi?id=13487
Summary
Implement O(1) absoluteClippedOverflowRect and absoluteOutlineBox during layo...
mitz
Reported
2007-04-25 11:06:04 PDT
When a block nested n levels deep needs relayout, O(n) implementations of absoluteClippedOverflowRect() and absoluteOutlineBox() are invoked by each of the ancestors, making for O(n^2) complexity. By keeping track of absolute coordinates and clip on the stack during layout, it should be possible to implement absoluteClippedOverflowRect() and absoluteOutlineBox() in O(1) during layout.
Attachments
Cursory patch
(22.20 KB, patch)
2007-04-25 11:23 PDT
,
mitz
no flags
Details
Formatted Diff
Diff
A test
(1.56 KB, text/html)
2007-04-26 00:32 PDT
,
mitz
no flags
Details
Baseline test results
(136 bytes, text/plain)
2007-04-26 00:33 PDT
,
mitz
no flags
Details
Test results after applying the patch
(130 bytes, text/plain)
2007-04-26 00:33 PDT
,
mitz
no flags
Details
Patch r0.4
(29.45 KB, patch)
2007-04-26 16:13 PDT
,
mitz
no flags
Details
Formatted Diff
Diff
Baseline test results for r21123
(140 bytes, text/plain)
2007-04-26 16:17 PDT
,
mitz
no flags
Details
Test results after applying patch r0.4 to r21123
(130 bytes, text/plain)
2007-04-26 16:20 PDT
,
mitz
no flags
Details
Keep track of absolute translation and clip during layout
(41.10 KB, patch)
2007-04-27 12:55 PDT
,
mitz
hyatt
: review-
Details
Formatted Diff
Diff
Keep track of absolute translation and clip during layout
(102.96 KB, patch)
2007-04-28 10:44 PDT
,
mitz
hyatt
: review-
Details
Formatted Diff
Diff
Keep track of absolute translation and clip during layout
(103.10 KB, patch)
2007-04-29 06:47 PDT
,
mitz
darin
: review+
Details
Formatted Diff
Diff
Show Obsolete
(4)
View All
Add attachment
proposed patch, testcase, etc.
mitz
Comment 1
2007-04-25 11:23:26 PDT
Created
attachment 14178
[details]
Cursory patch Implements the suggested optimization with some caveats: (1) only the root layer is optimized (2) subtree layout is disabled (3) SVG is not patched (4) some other RenderObject subclasses are not patched yet (5) it is not thoroughly tested (it passes existing repaint tests) (6) some code duplication. Before I address those I'd like to know if it's worth it. Perhaps someone with access to the PLT and/or interesting test cases would like to help.
Geoffrey Garen
Comment 2
2007-04-25 11:44:00 PDT
Dave, can you check this with the nesting PLT?
mitz
Comment 3
2007-04-25 11:54:53 PDT
(In reply to
comment #2
)
> Dave, can you check this with the nesting PLT? >
Hyatt mentioned on IRC a page that was "getting pwned by absolutePosition" and that computeAbsoluteRepaintRect was the "top offender for deeply nested inlines" (after applying some of his optimizations). I suppose it was in reference to non-cached pages, where image loading causes a ton of incremental relayout. In fact, for initial layout this patch may turn out to be bad, since it pushes state even if !checkForRepaint. Perhaps that can be avoided.
Dave Hyatt
Comment 4
2007-04-25 12:15:30 PDT
Your patch to RenderObject could be landed separately (the fixed position thing). By the way, my lazy minmaxwidth patch does fix the common O(n^2) problem with absoluteClippedOverflowRect (normal document construction) by making sure it does no work if inlines have no line boxes.
mitz
Comment 5
2007-04-26 00:32:08 PDT
Created
attachment 14194
[details]
A test
mitz
Comment 6
2007-04-26 00:33:05 PDT
Created
attachment 14195
[details]
Baseline test results
mitz
Comment 7
2007-04-26 00:33:48 PDT
Created
attachment 14196
[details]
Test results after applying the patch
mitz
Comment 8
2007-04-26 00:35:31 PDT
I don't know that the test is meaningful nor that the improvement is significant.
mitz
Comment 9
2007-04-26 00:50:56 PDT
In unscientific Shark profiles of the test, absolutePositon and computeAbsoluteRepaintRect come up at the top in TOT with 11.6% and 10.2%, respectively. With the patch they are down to 0.4% and 0.6%, resp.
Dave Hyatt
Comment 10
2007-04-26 10:43:37 PDT
Here are the top offenders on the nesting PLT: 15% WebCore::RenderObject::containingBlock() const 11% WebCore::RenderFlow::dirtyLinesFromChangedChild(WebCore::RenderObject*) 11% WebCore::RenderObject::repaint(bool) 9% WebCore::RenderBox::computeAbsoluteRepaintRect(WebCore::IntRect&, bool) 4% WebCore::RenderBox::absolutePosition(int&, int&, bool) const Excluding containingBlock turns into: 15% WebCore::RenderObject::invalidateContainingBlockPrefWidths() Which breaks down into 10% appendChildNode and 5% removeChildNode. It's clear from that profile that this change to make these O(1) will be a win. I think I should probably fix invalidatePrefWidths to use container() so that intermediate inlines are not skipped, since not dirtying the inlines is introducing O(n^2) behavior into this method as inlines nest deeply.
Dave Hyatt
Comment 11
2007-04-26 10:53:29 PDT
Filed
http://bugs.webkit.org/show_bug.cgi?id=13503
on the invalidateContainingBlockPrefWidths issue
Dave Hyatt
Comment 12
2007-04-26 12:55:26 PDT
OK, after the two fixes I landed today, computeAbsoluteRepaintRect and absolutePosition now dominate the nesting PLT (20% of the time). repaintObjectsBeforeLayout is 2%.
mitz
Comment 13
2007-04-26 16:13:54 PDT
Created
attachment 14215
[details]
Patch r0.4 Moved LayoutState from the stack to the RenderArena and eliminated some duplicate code. (1)-(5) of
comment #1
are mostly still not addressed.
mitz
Comment 14
2007-04-26 16:17:25 PDT
Created
attachment 14216
[details]
Baseline test results for
r21123
The baseline results are worse than before (
attachment 14195
[details]
). I suspect that's a result of removing the setLayout(false) from layoutBlockChildren in one of the recent revisions.
mitz
Comment 15
2007-04-26 16:20:20 PDT
Created
attachment 14217
[details]
Test results after applying patch r0.4 to
r21123
Shark shows absolutePosition and computeAbsoluteRepaintRect down from 11.4% and 9.9% to 0.5% and 0.5%.
mitz
Comment 16
2007-04-27 12:55:43 PDT
Created
attachment 14236
[details]
Keep track of absolute translation and clip during layout No change log yet, but ready for review. No layout/pixel test regressions.
Dave Hyatt
Comment 17
2007-04-27 14:22:57 PDT
Comment on
attachment 14236
[details]
Keep track of absolute translation and clip during layout I don't think you need to add the boxLayer() method. The cost of layer() is completely negligible if you get the O(n^2) stuff out of the way. I know it looks like it mattered because I added that hasLayer() stuff recently, but it was really only showing up because it was being called a ludicrous number of times (and even then it was only like 1%).
Dave Hyatt
Comment 18
2007-04-27 14:24:14 PDT
I know it breaks encapsulation, but IMO you can just use m_layer directly if you want. That's what I do in other places. This isn't a situation where that's going to change anyway. :)
mitz
Comment 19
2007-04-28 10:44:21 PDT
Created
attachment 14243
[details]
Keep track of absolute translation and clip during layout Includes change log, new test results (eliminated some excessive repainting) and one new test.
Darin Adler
Comment 20
2007-04-28 13:50:15 PDT
Comment on
attachment 14243
[details]
Keep track of absolute translation and clip during layout LayoutState should inherit from Noncopyable. + struct LayoutState* m_next; LayoutState is a class not a struct, but also, just LayoutState* should work here. + // Our layuot state is not valid for the repaints we are going to trigger by Typo, layuot. + bool layoutOnlyPositionedObjects(); The verb form is "layOut" and the noun form is "layout". I know that the layout() function violates this, but layOutAxis() respects it. I'm not sure others would agree with my take on this. + void offsetUnderRelPositionedInline(RenderObject*, int& x, int& y) const; I'm not completely comfortable with the verb use of offset here either. Ideally long-term something like this would return an IntSize that you would then add to your existing local IntPoint variable with +=. + // FIXME: Optimize using LayuotState and remove the disableLayoutState() call Typo here, LayuoutState. Given the paired nature of push/pop and disable/enable, perhaps we should use stack-based objects with destructors to ensure we don't forget to match them up. We could even make ones with features to cleanly deal with cases like the ones that currently have pushedLayoutState booleans. + void pushLayoutState(RenderBox* renderer, const IntSize& offset) { + if (m_layoutStateDisableCount || m_frameView->needsFullRepaint()) + return; + m_layoutState = new (renderArena()) LayoutState(m_layoutState, renderer, offset); + } I think we should put braces on separate lines for multiline functions, even ones that are inlines in a header. The style guidelines should say something about this if they don't already. I think Hyatt should review this too; I'm not sure I understand the optimization well enough.
mitz
Comment 21
2007-04-28 14:36:14 PDT
(In reply to
comment #20
)
> (From update of
attachment 14243
[details]
[edit]) > Typo, layuot.
Oops :-)
> + bool layoutOnlyPositionedObjects(); > > The verb form is "layOut" and the noun form is "layout". I know that the > layout() function violates this, but layOutAxis() respects it. I'm not sure > others would agree with my take on this.
It's not just layout(), it's layoutBlock(), layoutPositionedObjects(), layout{Block,Inline}Children() and maybe a few others. I agree that layOut is better but I would prefer not to introduce apparent inconsistency with this patch, and perhaps rename all such functions in a separate rename-only patch.
> + void offsetUnderRelPositionedInline(RenderObject*, int& x, int& y) const; > > I'm not completely comfortable with the verb use of offset here either.
I'm not comfortable with the entire name. I think "under" can be confusing.
> Ideally > long-term something like this would return an IntSize that you would then add > to your existing local IntPoint variable with +=.
I might just change it to return IntSize. I'm trying to use IntSize and IntPoint in new code. I started writing this function to return an IntSize but then I realized that the three existing callers had separate ints and decided not to bother with it.
> Typo here, LayuoutState.
Oops again :-}
> I think we should put braces on separate lines for multiline functions, even > ones that are inlines in a header.
I agree. This was unintentional. (Comments that I didn't quote and reply to I'm going to address, or at least try to address).
Dave Hyatt
Comment 22
2007-04-28 21:03:33 PDT
While "lay out" is correct English for the verb form, I still don't think we should use "layOut" anywhere in our code base. We should fix the frame function name to be "layout" instead. I think we basically have an established "web engine" colloquialism that treats layout as a single-word verb, and it would create an annoying inconsistency if we had methods like "setNeedsLayout" vs. "layOut."
Dave Hyatt
Comment 23
2007-04-28 21:11:11 PDT
Comment on
attachment 14243
[details]
Keep track of absolute translation and clip during layout Please fix the LayuotState typos and then I can r+.
mitz
Comment 24
2007-04-29 06:47:40 PDT
Created
attachment 14265
[details]
Keep track of absolute translation and clip during layout Changes from the previous patch: * renamed offsetUnderRelPositionedInline to offsetForPositionedInContainer and changed it return an IntSize. * Made LayoutState NonCopyable and removed the "struct" in the definition. * Fixed embarrassing typos! * Moved opening braces in multiline functions to a separate line.
Darin Adler
Comment 25
2007-04-29 07:34:30 PDT
Comment on
attachment 14265
[details]
Keep track of absolute translation and clip during layout r=me
Sam Weinig
Comment 26
2007-04-29 13:29:52 PDT
Landed in
r21183
.
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