Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 7d1d62ffe5fa58d48631c47750b62ceb59b9d019
      
https://github.com/WebKit/WebKit/commit/7d1d62ffe5fa58d48631c47750b62ceb59b9d019
  Author: Wenson Hsieh <[email protected]>
  Date:   2023-09-08 (Fri, 08 Sep 2023)

  Changed paths:
    M Source/WebCore/dom/ScriptedAnimationController.cpp
    M Source/WebCore/dom/ScriptedAnimationController.h
    M Source/WebCore/page/DOMTimer.cpp
    M Source/WebCore/page/DOMTimer.h
    M Source/WebCore/page/OpportunisticTaskScheduler.cpp
    M Source/WebCore/page/OpportunisticTaskScheduler.h
    M Source/WebCore/page/Page.cpp
    M Source/WebCore/page/Page.h

  Log Message:
  -----------
  Teach the opportunistic task scheduler about zero-delay timers and 
requestAnimationFrame
https://bugs.webkit.org/show_bug.cgi?id=261205
rdar://113237238

Reviewed by Yusuke Suzuki.

Refine heuristics used to schedule incremental sweeping in 
`OpportunisticTaskScheduler`, such that
it's aware of both one-shot zero-delay timers and pending rAF callbacks. 
Earlier versions of this
task scheduler (prior to `266680@main`) attempted to avoid scheduling work in 
both DOM timers and
rAF by exiting early if any `OpportunisticTaskDeferralScope` was held, but this 
has the additional
effect of preventing opportunistic tasks from being scheduled in many cases 
where it's necessary to
maintain performance on some critical benchmarks. As such, our current approach 
ignores pending
timers and rAF altogether, and simply schedules an opportunistic task at the 
first turn of the
runloop after finalizing a rendering update.

We take a slightly different approach in this patch; rather than limit 
opportunistically scheduled
tasks to non-deferral scopes, we instead use information about whether there is 
imminently scheduled
work as one of several pieces of information used to heurisitcally choose when 
to schedule
opportunistic tasks.

See below for more details.

* Source/WebCore/dom/ScriptedAnimationController.cpp:
(WebCore::ScriptedAnimationController::registerCallback):
(WebCore::ScriptedAnimationController::serviceRequestAnimationFrameCallbacks):
* Source/WebCore/dom/ScriptedAnimationController.h:

Grab a `ImminentlyScheduledWorkScope` while a rAF callback is pending.

* Source/WebCore/page/DOMTimer.cpp:
(WebCore::DOMTimer::install):
(WebCore::DOMTimer::removeById):
(WebCore::DOMTimer::fired):
(WebCore::DOMTimer::stop):
(WebCore::DOMTimer::makeImminentlyScheduledWorkScopeIfPossible):
(WebCore::DOMTimer::clearImminentlyScheduledWorkScope):
* Source/WebCore/page/DOMTimer.h:

Similarly, grab a `ImminentlyScheduledWorkScope` when a one-shot, low-delay DOM 
timer is pending.

This essentially restores the codepath that was removed in `266680@main`, but 
renames the "task
deferral" scopes to "imminently scheduled work" instead, to reflect the fact 
that it's only used to
provide a hint to the scheduler that there's imminently scheduled work.

* Source/WebCore/page/OpportunisticTaskScheduler.cpp:
(WebCore::OpportunisticTaskScheduler::reschedule):

We also turn `OpportunisticTaskScheduler` into a repeating runloop observer, so 
that we can choose
which runloop after a rendering update we should schedule the opportunistic 
task (or none at all).
We currently always schedule an opportunistic task after the first turn of the 
runloop after
finalizing the rendering update, but with this patch, we may now wait for a few 
turns of the runloop
to pass before scheduling the task (or we may not schedule a task during the 
rendering update at
all).

(WebCore::OpportunisticTaskScheduler::makeScheduledWorkScope):
(WebCore::OpportunisticTaskScheduler::runLoopObserverFired):

Implement the main heuristic here — if we have no imminent work, we schedule 
the opportunistic task
right away (matching behavior on trunk). Otherwise, we'll schedule work only if 
we have (relatively)
a lot of time until the next rendering update, or if the runloop has turned at 
least a few times
since the end of the rendering update. We start with this simple heuristic for 
now; in subsequent
patches, we'll continue to refine this heuristic to account for additional 
signals such as heap
size and object count, current GC phase, and other state from JavaScriptCore.

Note that we preserve the existing behavior of scheduling at most one 
opportunistic task per
rendering update. In future patches (especially if we can further quantize GC 
phases), we should
also consider allowing multiple opportunistic tasks per rendering update, at 
much smaller time
slices.

(WebCore::ImminentlyScheduledWorkScope::ImminentlyScheduledWorkScope):
(WebCore::ImminentlyScheduledWorkScope::~ImminentlyScheduledWorkScope):

Rename `OpportunisticTaskDeferralScope` to `ImminentlyScheduledWorkScope`, to 
better reflect the
fact that it's only used to provide a hint to the scheduler that there's 
imminently scheduled work,
rather than always deferring opportunistic tasks during the scope.

(WebCore::OpportunisticTaskDeferralScope::OpportunisticTaskDeferralScope): 
Deleted.
(WebCore::OpportunisticTaskDeferralScope::~OpportunisticTaskDeferralScope): 
Deleted.
(WebCore::OpportunisticTaskScheduler::makeDeferralScope): Deleted.
(WebCore::OpportunisticTaskScheduler::incrementDeferralCount): Deleted.
(WebCore::OpportunisticTaskScheduler::decrementDeferralCount): Deleted.
* Source/WebCore/page/OpportunisticTaskScheduler.h:
(WebCore::ImminentlyScheduledWorkScope::create):
(WebCore::OpportunisticTaskScheduler::hasImminentlyScheduledWork const):
* Source/WebCore/page/Page.cpp:
(WebCore::Page::didCommitLoad):
(WebCore::Page::didFirstMeaningfulPaint):

Replace the task deferral scope here with just a simple boolean flag indicating 
whether we're
waiting for the first meaningful paint. If so, we'll bail from opportunistic 
tasks altogether.

(WebCore::Page::opportunisticallyRunIdleCallbacks):

Split out logic for scheduling idle callbacks from the rest of the 
opportunistically scheduled
tasks, so that we can safely bail if the page itself is destroyed during idle 
callbacks. We also
move the `TraceScope` to `OpportunisticTaskScheduler`, where we already have 
the (approximate)
remaining time — this allows us to avoid an extra syscall to 
`mach_absolute_time` when creating the
trace scope.

(WebCore::Page::performOpportunisticallyScheduledTasks):
* Source/WebCore/page/Page.h:
(WebCore::Page::isWaitingForFirstMeaningfulPaint const):

Remove the former task deferral scope used to avoid opportunistic tasks prior 
to first meaningful
paint; instead, just make this a boolean flag and return early from 
`OpportunisticTaskScheduler` in
the case when it's set.

Canonical link: https://commits.webkit.org/267818@main


_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to