0

Teach the opportunistic task scheduler about zero-delay timers and re… · WebKit/...

 4 weeks ago
source link: https://github.com/WebKit/WebKit/commit/7d1d62ffe5fa58d48631c47750b62ceb59b9d019
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Commit

Permalink

Teach the opportunistic task scheduler about zero-delay timers and re…

Browse files Browse the repository at this point in the history

…questAnimationFrame

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
whsieh committed Sep 9, 2023
1 parent 9435b85 commit 7d1d62f

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK