Bug 207931 - [macOS] Disable RunLoop function dispatch when there is a pending rendering update
Summary: [macOS] Disable RunLoop function dispatch when there is a pending rendering u...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Layout and Rendering (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Antti Koivisto
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2020-02-19 02:25 PST by Antti Koivisto
Modified: 2020-02-20 11:43 PST (History)
14 users (show)

See Also:


Attachments
wip (6.03 KB, patch)
2020-02-19 02:26 PST, Antti Koivisto
no flags Details | Formatted Diff | Diff
patch (9.56 KB, patch)
2020-02-19 06:32 PST, Antti Koivisto
no flags Details | Formatted Diff | Diff
patch (9.56 KB, patch)
2020-02-19 07:02 PST, Antti Koivisto
no flags Details | Formatted Diff | Diff
patch (9.57 KB, patch)
2020-02-19 07:09 PST, Antti Koivisto
no flags Details | Formatted Diff | Diff
patch (9.57 KB, patch)
2020-02-19 11:35 PST, Antti Koivisto
no flags Details | Formatted Diff | Diff
patch (6.16 KB, patch)
2020-02-20 00:51 PST, Antti Koivisto
no flags Details | Formatted Diff | Diff
patch (8.68 KB, patch)
2020-02-20 03:58 PST, Antti Koivisto
no flags Details | Formatted Diff | Diff
patch (5.80 KB, patch)
2020-02-20 04:01 PST, Antti Koivisto
no flags Details | Formatted Diff | Diff
patch (5.78 KB, patch)
2020-02-20 05:33 PST, Antti Koivisto
no flags Details | Formatted Diff | Diff
patch (7.28 KB, patch)
2020-02-20 05:50 PST, Antti Koivisto
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Antti Koivisto 2020-02-19 02:25:01 PST
Avoid processing async IPC until rendering update happens.
Comment 1 Antti Koivisto 2020-02-19 02:26:16 PST
Created attachment 391149 [details]
wip
Comment 2 Antti Koivisto 2020-02-19 06:32:16 PST
Created attachment 391154 [details]
patch
Comment 3 Antti Koivisto 2020-02-19 07:02:00 PST
Created attachment 391156 [details]
patch
Comment 4 Antti Koivisto 2020-02-19 07:09:26 PST
Created attachment 391158 [details]
patch
Comment 5 Antti Koivisto 2020-02-19 08:54:35 PST
The patch doesn't affect WK1, the failure is a flake.
Comment 6 Ben Nham 2020-02-19 09:23:11 PST
Comment on attachment 391158 [details]
patch

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

> Source/WebCore/dom/WindowEventLoop.h:85
> +    static bool m_hasPendingRenderingUpdate;

Should this be a member variable rather than a static variable?
Comment 7 Antti Koivisto 2020-02-19 10:46:06 PST
> Should this be a member variable rather than a static variable?

Maybe later. For now this is simplest and waiting-for-flush really is a process global state.
Comment 8 Ben Nham 2020-02-19 10:47:31 PST
(In reply to Antti Koivisto from comment #7)
> > Should this be a member variable rather than a static variable?
> 
> Maybe later. For now this is simplest and waiting-for-flush really is a
> process global state.

I see. Maybe make it use the s_ prefix rather than m_ prefix then? It seems like we follow that pattern for static variables in a lot of places.
Comment 9 Antti Koivisto 2020-02-19 11:32:38 PST
> I see. Maybe make it use the s_ prefix rather than m_ prefix then? It seems
> like we follow that pattern for static variables in a lot of places.

Ah right. Good point.
Comment 10 Antti Koivisto 2020-02-19 11:35:49 PST
Created attachment 391183 [details]
patch
Comment 11 Simon Fraser (smfr) 2020-02-19 11:40:06 PST
Comment on attachment 391158 [details]
patch

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

> Source/WTF/wtf/RunLoop.h:187
> +    bool m_isFunctionDispatchSuspended { false };

Should this be separate from a 'has pending rendering update?

> Source/WTF/wtf/cf/RunLoopCF.cpp:67
>  RunLoop::CycleResult RunLoop::cycle(RunLoopMode mode)
>  {
> +    main().setFunctionDispatchSuspended(false);

Can this be called on any runloop? Why would, say, the scrolling thread runloop care about whether function dispatch is enabled on the main runloop?

> Source/WebCore/dom/WindowEventLoop.cpp:173
> +    if (m_hasPendingRenderingUpdate) {
> +        // FIXME: Also bail out from the task loop in EventLoop::run().
> +        threadGlobalData().threadTimers().breakFireLoopForRenderingUpdate();
> +    }
>  
> +    RunLoop::main().setFunctionDispatchSuspended(m_hasPendingRenderingUpdate);

awkward that these are different.

>> Source/WebCore/dom/WindowEventLoop.h:85
>> +    static bool m_hasPendingRenderingUpdate;
> 
> Should this be a member variable rather than a static variable?

Agreed; using the m_ prefix seems like it will lead to coding errors in future.
Comment 12 Geoffrey Garen 2020-02-19 11:47:08 PST
Comment on attachment 391183 [details]
patch

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

> Source/WTF/wtf/RunLoop.cpp:105
> +            if (m_isFunctionDispatchSuspended)
> +                return;

It's kind of scary to allow ourselves to get into a permanently disabled state (if someone forgets to make the balancing call to setFunctionDispatchSuspended()).

Instead of a persistent setting, can we make this a one-shot behavior that automatically clears itself and then re-schedules a wakeUp()? I believe that would be sufficient to allow any scheduled rendering update to complete in the current runloop iteration.

We could call this deferring the next runloop iteration, rather than suspending it entirely.
Comment 13 Antti Koivisto 2020-02-19 11:52:23 PST
> Should this be separate from a 'has pending rendering update?

I didn't want to push the concept of rendering update to WTF.

> Can this be called on any runloop? Why would, say, the scrolling thread
> runloop care about whether function dispatch is enabled on the main runloop?

It is only used (and probably useful) for JS debugger.

> awkward that these are different.

Different abstraction levels. I don't find that particularly awkward.

> Agreed; using the m_ prefix seems like it will lead to coding errors in
> future.

Fixed with s_
Comment 14 Antti Koivisto 2020-02-19 11:56:22 PST
> It's kind of scary to allow ourselves to get into a permanently disabled
> state (if someone forgets to make the balancing call to
> setFunctionDispatchSuspended()).
> 
> Instead of a persistent setting, can we make this a one-shot behavior that
> automatically clears itself and then re-schedules a wakeUp()? I believe that
> would be sufficient to allow any scheduled rendering update to complete in
> the current runloop iteration.
> 
> We could call this deferring the next runloop iteration, rather than
> suspending it entirely.

I thought about it. The cost is that we may unnecessarily skip the cycle after the rendering update has already happened (since we won't know if the current one will in fact end up waking up). I'm not sure if that is a problem in practice. Maybe not.
Comment 15 Geoffrey Garen 2020-02-19 12:25:08 PST
> > We could call this deferring the next runloop iteration, rather than
> > suspending it entirely.
> 
> I thought about it. The cost is that we may unnecessarily skip the cycle
> after the rendering update has already happened (since we won't know if the
> current one will in fact end up waking up). I'm not sure if that is a
> problem in practice. Maybe not.

Maybe the act of deferring could also schedule a wakeup? That would eagerly clear the deferred state at the end of the runloop, so that future wakeups would not be delayed.
Comment 16 Antti Koivisto 2020-02-19 12:59:31 PST
Yeah, that would work. I’ll do that.
Comment 17 Simon Fraser (smfr) 2020-02-19 13:05:39 PST
Comment on attachment 391183 [details]
patch

I'm a bit concerned that we're repeating the mistake of layer tree freezing and all the timers, and putting throttling/event loop logic in too many places.

Can we move the calls into WebCore::WindowEventLoop into WebCore (maybe via something on Page)? Maybe start to put all the throttling logic in one place.
Comment 18 Antti Koivisto 2020-02-20 00:51:59 PST
Created attachment 391267 [details]
patch
Comment 19 Antti Koivisto 2020-02-20 00:52:19 PST
Now with less state.
Comment 20 Antti Koivisto 2020-02-20 03:58:03 PST
Created attachment 391275 [details]
patch
Comment 21 Antti Koivisto 2020-02-20 04:01:42 PST
Created attachment 391276 [details]
patch
Comment 22 Antti Koivisto 2020-02-20 05:33:51 PST
Created attachment 391279 [details]
patch
Comment 23 Antti Koivisto 2020-02-20 05:50:55 PST
Created attachment 391281 [details]
patch
Comment 24 Geoffrey Garen 2020-02-20 10:13:30 PST
Comment on attachment 391281 [details]
patch

r=me

I do think it would be nice to establish a central controller that manages all layout/paint "throttling". That said, I think this behavior is a little lower level, and probably something that central controller will call into. This behavior is about acknowledging that some system feature needs to run in the runloop without being preempted by other expensive WebKit runloop work.
Comment 25 Simon Fraser (smfr) 2020-02-20 11:13:56 PST
Comment on attachment 391281 [details]
patch

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

> Source/WTF/wtf/RunLoop.cpp:145
> +    // Wake up even if there is nothing to do to disable suspension.

"to do to" Maybe Wake up (even if there is nothing to do) to disable suspension.
Comment 26 Antti Koivisto 2020-02-20 11:15:05 PST
For this sort of things I think WindowEventLoop (that is the HTML event loop) is the right central place as we'll eventually want to handle all task scheduling activities there (including IPC, networking, timers,...).

Throttling is a mostly unrelated concept.
Comment 27 WebKit Commit Bot 2020-02-20 11:22:16 PST
Comment on attachment 391281 [details]
patch

Clearing flags on attachment: 391281

Committed r257072: <https://trac.webkit.org/changeset/257072>
Comment 28 WebKit Commit Bot 2020-02-20 11:22:19 PST
All reviewed patches have been landed.  Closing bug.
Comment 29 Radar WebKit Bug Importer 2020-02-20 11:23:13 PST
<rdar://problem/59636696>
Comment 30 Antti Koivisto 2020-02-20 11:43:01 PST
Comment fix https://trac.webkit.org/r257076