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