Bug 228673 - [GPUProcess] REGRESSION: A noticeable slow down when browsing Live Photos album on iCloud.com
Summary: [GPUProcess] REGRESSION: A noticeable slow down when browsing Live Photos alb...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Canvas (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Said Abou-Hallawa
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2021-07-30 17:27 PDT by Said Abou-Hallawa
Modified: 2022-04-26 20:36 PDT (History)
4 users (show)

See Also:


Attachments
Patch (2.35 KB, patch)
2021-07-30 19:45 PDT, Said Abou-Hallawa
no flags Details | Formatted Diff | Diff
Patch (2.14 KB, patch)
2021-08-03 17:18 PDT, Said Abou-Hallawa
no flags Details | Formatted Diff | Diff
Patch (1.99 KB, patch)
2021-08-04 00:01 PDT, Said Abou-Hallawa
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Said Abou-Hallawa 2021-07-30 17:27:15 PDT
Appending FlushContext to the DL makes GPUProcess do two things:
1. Flushes the backend context.
2. Sends a DidFlush message back to the WebProcess.

One of the callers of RemoteImageBufferProxy::flushDrawingContextAsync() is RemoteImageBufferProxy::flushDrawingContext() which assumes FlushContext is added all the times and this is why it waits for 3 seconds and then gives up. But flushDrawingContextAsync() adds FlushContext only 'if (!m_drawingContext.displayList().isEmpty())'. The opposite can happen very often since clearDisplayList() is called from flushDrawingContextAsync() itself. So we can waste three seconds waiting for a message that will never be received because the DisplayList is empty.

If 'm_drawingContext.displayList().isEmpty()' is true, appending FlushContext may not be needed. But we do not know for sure if the GPUProcess is applying or will be applying items from the SharedBuffer for this ImageBuffer. We need to ensure all the items are processed and we may be waiting for a DidFlush message. So the solution is to make RemoteImageBufferProxy::flushDrawingContextAsync() append FlushContext to its DisplayList always.
Comment 1 Said Abou-Hallawa 2021-07-30 19:45:39 PDT
Created attachment 434683 [details]
Patch
Comment 2 Radar WebKit Bug Importer 2021-07-30 19:46:53 PDT
<rdar://problem/81353138>
Comment 3 Wenson Hsieh 2021-08-02 10:09:50 PDT
Comment on attachment 434683 [details]
Patch

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

Is there a reason why we don't just check `!m_drawingContext.displayList().isEmpty()` in `flushDrawingContext()`?

> Source/WebKit/ChangeLog:15
> +        the backend context is flushed. Also we need GPUProces to send the DidFush

Nits - GPUProces => GPUProcess, DidFush => DidFlush
Comment 4 Said Abou-Hallawa 2021-08-03 17:18:44 PDT
Created attachment 434872 [details]
Patch
Comment 5 Said Abou-Hallawa 2021-08-03 17:30:07 PDT
Comment on attachment 434683 [details]
Patch

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

I replaced 'if (!m_drawingContext.displayList().isEmpty())' by 'if (!hasPendingFlush())'. I think this makes more sense.

Suppose CanvasRenderingContext2DBase::prepareForDisplay() calls RemoteImageBufferProxy::flushDrawingContextAsync() and this one adds the FlushContext item. Later and before we receive the DidFlush, ConcreteImageBuffer::copyNativeImage() calls flushDrawingContext(). In this case we will realize there is a pending FlushContext and we are not going to send a new one. We wait for DidFlush and it arrives as expected.

Now suppose for example the destructor RemoteImageBufferProxy::~RemoteImageBufferProxy() calls flushDrawingContext(). It will add the FlushContext since it does not have a pending one. flushDrawingContext() waits for DidFlush and it arrives as expected.

>> Source/WebKit/ChangeLog:15
>> +        the backend context is flushed. Also we need GPUProces to send the DidFush
> 
> Nits - GPUProces => GPUProcess, DidFush => DidFlush

Fixed.
Comment 6 Said Abou-Hallawa 2021-08-04 00:01:24 PDT
Created attachment 434890 [details]
Patch
Comment 7 Said Abou-Hallawa 2021-08-04 12:22:19 PDT
I changed the patch to add !hasPendingFlush() as a condition to add FlushContext item.

Keeping the condition "!m_drawingContext.displayList().isEmpty()" will help with a sequence like the following:

    FillRect       // Drawing to RemoteImageBufferProxy
    ...
    FlushContext   // Added by flushDrawingContextAsync() because the DL is not empty (there is no pending FlushContext)
    ...
    StrokeRect     // Continue drawing to RemoteImageBufferProxy
    ...
    FlushContext   // Added by flushDrawingContextAsync() because the DL is not empty (there is a pending FlushContext)

The condition "!hasPendingFlush()" will add the FlushContext even if the DL is empty which will force sending WakeUpAndApplyDisplayList to GPUP so we can guarantee the GPUP will send a DidFlush message.
Comment 8 EWS 2021-08-04 12:43:07 PDT
Committed r280652 (240263@main): <https://commits.webkit.org/240263@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 434890 [details].