RESOLVED FIXED 207931
[macOS] Disable RunLoop function dispatch when there is a pending rendering update
https://bugs.webkit.org/show_bug.cgi?id=207931
Summary [macOS] Disable RunLoop function dispatch when there is a pending rendering u...
Antti Koivisto
Reported 2020-02-19 02:25:01 PST
Avoid processing async IPC until rendering update happens.
Attachments
wip (6.03 KB, patch)
2020-02-19 02:26 PST, Antti Koivisto
no flags
patch (9.56 KB, patch)
2020-02-19 06:32 PST, Antti Koivisto
no flags
patch (9.56 KB, patch)
2020-02-19 07:02 PST, Antti Koivisto
no flags
patch (9.57 KB, patch)
2020-02-19 07:09 PST, Antti Koivisto
no flags
patch (9.57 KB, patch)
2020-02-19 11:35 PST, Antti Koivisto
no flags
patch (6.16 KB, patch)
2020-02-20 00:51 PST, Antti Koivisto
no flags
patch (8.68 KB, patch)
2020-02-20 03:58 PST, Antti Koivisto
no flags
patch (5.80 KB, patch)
2020-02-20 04:01 PST, Antti Koivisto
no flags
patch (5.78 KB, patch)
2020-02-20 05:33 PST, Antti Koivisto
no flags
patch (7.28 KB, patch)
2020-02-20 05:50 PST, Antti Koivisto
no flags
Antti Koivisto
Comment 1 2020-02-19 02:26:16 PST
Antti Koivisto
Comment 2 2020-02-19 06:32:16 PST
Antti Koivisto
Comment 3 2020-02-19 07:02:00 PST
Antti Koivisto
Comment 4 2020-02-19 07:09:26 PST
Antti Koivisto
Comment 5 2020-02-19 08:54:35 PST
The patch doesn't affect WK1, the failure is a flake.
Ben Nham
Comment 6 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?
Antti Koivisto
Comment 7 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.
Ben Nham
Comment 8 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.
Antti Koivisto
Comment 9 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.
Antti Koivisto
Comment 10 2020-02-19 11:35:49 PST
Simon Fraser (smfr)
Comment 11 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.
Geoffrey Garen
Comment 12 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.
Antti Koivisto
Comment 13 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_
Antti Koivisto
Comment 14 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.
Geoffrey Garen
Comment 15 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.
Antti Koivisto
Comment 16 2020-02-19 12:59:31 PST
Yeah, that would work. I’ll do that.
Simon Fraser (smfr)
Comment 17 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.
Antti Koivisto
Comment 18 2020-02-20 00:51:59 PST
Antti Koivisto
Comment 19 2020-02-20 00:52:19 PST
Now with less state.
Antti Koivisto
Comment 20 2020-02-20 03:58:03 PST
Antti Koivisto
Comment 21 2020-02-20 04:01:42 PST
Antti Koivisto
Comment 22 2020-02-20 05:33:51 PST
Antti Koivisto
Comment 23 2020-02-20 05:50:55 PST
Geoffrey Garen
Comment 24 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.
Simon Fraser (smfr)
Comment 25 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.
Antti Koivisto
Comment 26 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.
WebKit Commit Bot
Comment 27 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>
WebKit Commit Bot
Comment 28 2020-02-20 11:22:19 PST
All reviewed patches have been landed. Closing bug.
Radar WebKit Bug Importer
Comment 29 2020-02-20 11:23:13 PST
Antti Koivisto
Comment 30 2020-02-20 11:43:01 PST
Note You need to log in before you can comment on or make changes to this bug.