Bug 229802

Summary: [Performance] Self painting layers spend too much time in RenderLayer::collectFragments
Product: WebKit Reporter: cathiechen <cathiechen>
Component: Layout and RenderingAssignee: cathiechen <cathiechen>
Status: NEW ---    
Severity: Normal CC: bfulgham, cdumez, changseok, esprehn+autocc, ews-watchlist, fred.wang, glenn, jbedard, kondapallykalyan, pdr, rbuis, rniwa, simon.fraser, webkit-bug-importer, zalan
Priority: P2 Keywords: InRadar
Version: WebKit Local Build   
Hardware: Unspecified   
OS: Unspecified   
See Also: https://bugs.webkit.org/show_bug.cgi?id=228696
https://bugs.webkit.org/show_bug.cgi?id=230885
https://bugs.webkit.org/show_bug.cgi?id=231016
https://bugs.webkit.org/show_bug.cgi?id=231169
Bug Depends on: 233684    
Bug Blocks:    
Attachments:
Description Flags
screen-shot-collectFragments-cost
none
test-change-first-child-height.html
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
screenshot-of-optimized-collectFragments
none
screenshot-of-original-collectFragments
none
Patch
none
Patch
none
screenshot-of-optimized-collectFragments
none
Patch
none
Patch-for-review
none
Patch none

Description cathiechen 2021-09-02 05:52:54 PDT
RenderLayer::collectFragments costs around 20% time in RenderLayer::collectFragments for this test.
Comment 1 cathiechen 2021-09-02 05:58:29 PDT
Created attachment 437140 [details]
screen-shot-collectFragments-cost
Comment 2 cathiechen 2021-09-02 06:00:12 PDT
Created attachment 437142 [details]
test-change-first-child-height.html
Comment 3 cathiechen 2021-09-02 10:11:27 PDT
Created attachment 437162 [details]
Patch
Comment 4 Simon Fraser (smfr) 2021-09-02 10:42:11 PDT
Comment on attachment 437162 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=437162&action=review

> Source/WebCore/rendering/RenderLayer.cpp:4591
> +    if (!paintDirtyRect.intersects(m_repaintRects.outlineBoundsRect))

This needs to check m_repaintRectsValid
Comment 5 cathiechen 2021-09-05 20:35:51 PDT
Comment on attachment 437162 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=437162&action=review

>> Source/WebCore/rendering/RenderLayer.cpp:4591
>> +    if (!paintDirtyRect.intersects(m_repaintRects.outlineBoundsRect))
> 
> This needs to check m_repaintRectsValid

Done, thanks!
Comment 6 cathiechen 2021-09-05 20:36:56 PDT
Created attachment 437376 [details]
Patch
Comment 7 cathiechen 2021-09-08 00:46:23 PDT
Created attachment 437606 [details]
Patch
Comment 8 Radar WebKit Bug Importer 2021-09-09 05:53:18 PDT
<rdar://problem/82921321>
Comment 9 cathiechen 2021-09-09 09:41:13 PDT
Created attachment 437754 [details]
Patch
Comment 10 cathiechen 2021-09-09 19:04:52 PDT
Created attachment 437822 [details]
Patch
Comment 11 Rob Buis 2021-09-10 00:17:56 PDT
Comment on attachment 437822 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=437822&action=review

> Source/WebCore/rendering/RenderLayer.cpp:3553
> +        return true;

With a transform in place there could still be no intersection I think? If so it is probably best to keep this check out of hasIntersections. Or rename to something like hasSimpleIntersections.
Comment 12 cathiechen 2021-09-11 09:03:03 PDT
Comment on attachment 437822 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=437822&action=review

>> Source/WebCore/rendering/RenderLayer.cpp:3553
>> +        return true;
> 
> With a transform in place there could still be no intersection I think? If so it is probably best to keep this check out of hasIntersections. Or rename to something like hasSimpleIntersections.

Thanks, looks like this can be removed.
Comment 13 cathiechen 2021-09-11 09:11:11 PDT
Created attachment 437952 [details]
Patch
Comment 14 cathiechen 2021-09-11 09:18:07 PDT
Created attachment 437954 [details]
screenshot-of-optimized-collectFragments
Comment 15 cathiechen 2021-09-11 09:18:53 PDT
Created attachment 437955 [details]
screenshot-of-original-collectFragments
Comment 16 cathiechen 2021-09-11 09:30:11 PDT
Hi,

I think the patch is ready for review.

According to the tests on my local Mac.
The function RenderLayer::collectFragments costs about 20% less (from 27% to 6.2%) while loading the test page.

A performance test has been added, which is based on requestAnimationFrame. The result is about 10% better.

Please take a look. Thanks:)
Comment 17 cathiechen 2021-09-15 02:49:32 PDT
Created attachment 438231 [details]
Patch
Comment 18 Simon Fraser (smfr) 2021-09-15 09:27:57 PDT
Comment on attachment 438231 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=438231&action=review

> Source/WebCore/rendering/RenderLayer.cpp:3552
> +    if (auto* box = renderBox(); box && box->hasRenderOverflow()) {

If a box has overflow, why can't we just check against m_repaintRects.clippedOverflowRect?
Comment 19 cathiechen 2021-09-24 10:14:21 PDT
Comment on attachment 438231 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=438231&action=review

>> Source/WebCore/rendering/RenderLayer.cpp:3552
>> +    if (auto* box = renderBox(); box && box->hasRenderOverflow()) {
> 
> If a box has overflow, why can't we just check against m_repaintRects.clippedOverflowRect?

Yes, we can remove this. I was trying to collect all the rects, including the descendants' which is not needed.

And it seems this approach will change the return value of collectFragments when there is backgroundClipRect.
I will try to upload a new patch that should not change the return value.
Comment 20 cathiechen 2021-09-24 10:45:47 PDT
Created attachment 439162 [details]
Patch
Comment 21 cathiechen 2021-09-24 10:51:12 PDT
The time is reduced from 27% to 15.2% with the new optimization.
Comment 22 cathiechen 2021-09-27 01:18:00 PDT
Created attachment 439328 [details]
screenshot-of-optimized-collectFragments
Comment 23 cathiechen 2021-09-27 01:24:19 PDT
Created attachment 439330 [details]
Patch
Comment 24 cathiechen 2021-09-27 20:17:01 PDT
Comment on attachment 439330 [details]
Patch

Hi,
I think the patch is ready for review now. Please take a look, thanks!
Comment 25 cathiechen 2021-09-28 03:10:18 PDT
The intersection check and the parentClipRects part are not very relevant, so I've split the parentClipRects changes to a new bug. (230885)
Comment 26 cathiechen 2021-09-28 03:25:06 PDT
Created attachment 439451 [details]
Patch-for-review
Comment 27 cathiechen 2021-10-05 00:39:06 PDT
Created attachment 440179 [details]
Patch
Comment 28 Rob Buis 2021-12-13 00:39:53 PST
Comment on attachment 439451 [details]
Patch-for-review

View in context: https://bugs.webkit.org/attachment.cgi?id=439451&action=review

> Source/WebCore/rendering/RenderLayer.cpp:4625
> +                foregroundRect = LayoutRect();

It seems at this point we can just return? Also is it possible to add a single block to handle the !intersectsBackgroundRect, rather than in three areas?
Comment 29 cathiechen 2021-12-13 01:09:49 PST
Comment on attachment 439451 [details]
Patch-for-review

View in context: https://bugs.webkit.org/attachment.cgi?id=439451&action=review

>> Source/WebCore/rendering/RenderLayer.cpp:4625
>> +                foregroundRect = LayoutRect();
> 
> It seems at this point we can just return? Also is it possible to add a single block to handle the !intersectsBackgroundRect, rather than in three areas?

Yeah, indeed, we can return here.
BTW, we moved this fix to bug: 231169