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

Reply via email to