Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: c0b0499d32c9520d52b49e9742b003e61a596e7c
https://github.com/WebKit/WebKit/commit/c0b0499d32c9520d52b49e9742b003e61a596e7c
Author: Ryan Reno <[email protected]>
Date: 2025-10-28 (Tue, 28 Oct 2025)
Changed paths:
A LayoutTests/fast/dom/setInterval-aligned-when-nested-expected.txt
A LayoutTests/fast/dom/setInterval-aligned-when-nested.html
A LayoutTests/fast/dom/setTimeout-aligned-when-nested-expected.txt
A LayoutTests/fast/dom/setTimeout-aligned-when-nested.html
M Source/WTF/wtf/Seconds.h
M Source/WebCore/dom/Document.cpp
M Source/WebCore/dom/ScriptExecutionContext.h
M Source/WebCore/page/DOMTimer.cpp
M Source/WebCore/page/DOMTimer.h
M Source/WebCore/platform/Timer.cpp
M Source/WebCore/platform/Timer.h
M Source/WebCore/testing/Internals.cpp
M Source/WebCore/testing/Internals.h
M Source/WebCore/testing/Internals.idl
Log Message:
-----------
Align maximally nested DOM timers to 4 milliseconds
https://bugs.webkit.org/show_bug.cgi?id=300530
rdar://160531755
Reviewed by Ryosuke Niwa.
Aligning maximally nested DOM timers to a non-zero alignment can prevent
abandoned repeating timers
or a large volume of timers from keeping the main thread busy indefinitely. It
is especially bad if these
timers end up scheduling more timers which can cause an explosion in
outstanding timer-driven work. In the
worst case, the 16ms duty cycle limit for firing timers will be hit but we have
so much work backed up we only
sleep the main thread for a few tens of microseconds at most. This keeps CPU
perf states
elevated and drives thermal and power use issues.
As a mitigation, we can align DOM timers which have reached their maximum
nesting level to
4ms. We already clamp their timeouts to a 4ms minimum but this change will
additionally align timeouts to
the nearest 4ms multiple (+/- a randomized proportion, see
ScriptExecutionContext::alignedFireTime).
This mitigation is especially helpful on sites with many nested DOM timers or
on sites which inadvertantly
leak their DOM timer handles and abandon repeating timers to fire indefinitely.
By aligning
these timers to a 4ms multiple we end up lessening timer pile up back pressure
and we can sleep the
main thread for at least a few milliseconds at a time between rendering frames.
This prevents the main thread
from being more or less continuously scheduled and keeps the system from
putting the CPU into maximum perf states
for prolonged or even indefinite periods of time which can drive thermals and
draw excessive power.
This tested neutral on our benchmarks with the exception of PLT on iPhone where
it is a 4% progression.
* LayoutTests/fast/dom/setInterval-aligned-when-nested-expected.txt: Added.
* LayoutTests/fast/dom/setInterval-aligned-when-nested.html: Added.
* LayoutTests/fast/dom/setTimeout-aligned-when-nested-expected.txt: Added.
* LayoutTests/fast/dom/setTimeout-aligned-when-nested.html: Added.
Internals tests that check alignment happen when the respective DOM timer
reaches its
maximum nesting level. These are internals tests since trying to observe
alignment
from the web is extremely flaky. It's easier to tell if a zero-delay timer
has been
clamped, but smaller alignments for longer timeouts are very difficult to
observe
reliably.
* Source/WTF/wtf/Seconds.h:
(WTF::operator*):
(WTF::operator/):
These should be constexpr.
* Source/WebCore/dom/Document.cpp:
(WebCore::Document::domTimerAlignmentInterval const):
This is where the 4ms alignment is applied when the timer
has reached its max nesting level.
* Source/WebCore/dom/ScriptExecutionContext.h:
* Source/WebCore/page/DOMTimer.cpp:
(WebCore::ScriptExecutionContext::alignedFireTime const):
* Source/WebCore/page/DOMTimer.h:
The DOM timer interval defaults should be constexpr.
* Source/WebCore/platform/Timer.cpp:
(WebCore::TimerBase::setNextFireTime):
* Source/WebCore/platform/Timer.h:
Change the TimerAlignment interface from returning an optional fire time
to instead return a fire time directly, even if no alignment was applied.
There isn't a need to differentiate between aligned and unaligned fire times
being returned from this interface due to testing changes.
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::isTimerThrottled):
I adjusted this to account for the 4ms adjustment we will make
when a timer reaches the max nesting level. I'm not sure if we want to
call this throttled or not. It is worthwhile to distinguish between
throttled (like 1s for background timers, for instance) and aligned. The
former is obviously throttling but the latter is more of a slight adjustment
to timeouts in order to ensure the main thread is more efficiently
scheduled.
(WebCore::Internals::isTimerAligned):
* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:
Canonical link: https://commits.webkit.org/302278@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications