Changeset 185012 in webkit


Ignore:
Timestamp:
May 29, 2015 4:02:36 PM (9 years ago)
Author:
Chris Dumez
Message:

Consider throttling DOM timers in iframes outside the viewport
https://bugs.webkit.org/show_bug.cgi?id=145465
<rdar://problem/20768957>

Reviewed by Darin Adler.

Source/WebCore:

Throttle DOM timers in iframes that are outside the viewport to decrease
CPU usage, improve performance and reduce power use.

The approach is similar to what we already did for requestAnimationFrame
in r183998.

We already has support for throttling DOM timers at:

  • Page level: for backgound pages
  • DOM timer level: for timers changing the style of an element outside the viewport or drawing on a canvas outside the viewport.

This patch adds support for throttling DOM timers at Document level so
we can throttle all timers inside a specific iframe / Document. It relies
on the same timerAlignmentInterval that is used for throttling at Page
level with tweaks so that different Documents inside the same Page can
have a different timerAlignmentInterval.

Test: fast/dom/timer-throttling-subframe.html

  • dom/Document.cpp:

(WebCore::Document::setTimerThrottlingEnabled):
(WebCore::Document::timerAlignmentInterval):

  • dom/Document.h:

(WebCore::Document::isTimerThrottlingEnabled):

  • page/DOMTimer.cpp:

(WebCore::DOMTimer::alignedFireTime):
The previous code was not throttling the timer if its fireTime was in
the past. This was causing some aggressive timers on mashable.com to
not be throttled so I got rid of this behavior. I don't see any reason
why we would not throttle a timer simply because it is supposed to have
fired already.

  • page/FrameView.cpp:

(WebCore::FrameView::viewportContentsChanged):
(WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState):

  • page/FrameView.h:
  • testing/Internals.cpp:

(WebCore::Internals::areTimersThrottled):

  • testing/Internals.h:
  • testing/Internals.idl:

Add API to facilitate layout testing of this functionality.

LayoutTests:

Add a layout test to check that DOM timers in iframes outside the
viewport get throttled.

  • fast/dom/resources/timer-frame-2.html: Added.
  • fast/dom/resources/timer-frame.html: Added.
  • fast/dom/timer-throttling-subframe-expected.txt: Added.
  • fast/dom/timer-throttling-subframe.html: Added.
Location:
trunk
Files:
4 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r185002 r185012  
     12015-05-29  Chris Dumez  <cdumez@apple.com>
     2
     3        Consider throttling DOM timers in iframes outside the viewport
     4        https://bugs.webkit.org/show_bug.cgi?id=145465
     5        <rdar://problem/20768957>
     6
     7        Reviewed by Darin Adler.
     8
     9        Add a layout test to check that DOM timers in iframes outside the
     10        viewport get throttled.
     11
     12        * fast/dom/resources/timer-frame-2.html: Added.
     13        * fast/dom/resources/timer-frame.html: Added.
     14        * fast/dom/timer-throttling-subframe-expected.txt: Added.
     15        * fast/dom/timer-throttling-subframe.html: Added.
     16
    1172015-05-28  Filip Pizlo  <fpizlo@apple.com>
    218
  • trunk/Source/WebCore/ChangeLog

    r185007 r185012  
     12015-05-29  Chris Dumez  <cdumez@apple.com>
     2
     3        Consider throttling DOM timers in iframes outside the viewport
     4        https://bugs.webkit.org/show_bug.cgi?id=145465
     5        <rdar://problem/20768957>
     6
     7        Reviewed by Darin Adler.
     8
     9        Throttle DOM timers in iframes that are outside the viewport to decrease
     10        CPU usage, improve performance and reduce power use.
     11
     12        The approach is similar to what we already did for requestAnimationFrame
     13        in r183998.
     14
     15        We already has support for throttling DOM timers at:
     16        - Page level: for backgound pages
     17        - DOM timer level: for timers changing the style of an element outside
     18          the viewport or drawing on a canvas outside the viewport.
     19
     20        This patch adds support for throttling DOM timers at Document level so
     21        we can throttle all timers inside a specific iframe / Document. It relies
     22        on the same timerAlignmentInterval that is used for throttling at Page
     23        level with tweaks so that different Documents inside the same Page can
     24        have a different timerAlignmentInterval.
     25
     26        Test: fast/dom/timer-throttling-subframe.html
     27
     28        * dom/Document.cpp:
     29        (WebCore::Document::setTimerThrottlingEnabled):
     30        (WebCore::Document::timerAlignmentInterval):
     31        * dom/Document.h:
     32        (WebCore::Document::isTimerThrottlingEnabled):
     33        * page/DOMTimer.cpp:
     34        (WebCore::DOMTimer::alignedFireTime):
     35        The previous code was not throttling the timer if its fireTime was in
     36        the past. This was causing some aggressive timers on mashable.com to
     37        not be throttled so I got rid of this behavior. I don't see any reason
     38        why we would not throttle a timer simply because it is supposed to have
     39        fired already.
     40
     41        * page/FrameView.cpp:
     42        (WebCore::FrameView::viewportContentsChanged):
     43        (WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState):
     44        * page/FrameView.h:
     45
     46        * testing/Internals.cpp:
     47        (WebCore::Internals::areTimersThrottled):
     48        * testing/Internals.h:
     49        * testing/Internals.idl:
     50        Add API to facilitate layout testing of this functionality.
     51
    1522015-05-29  Brady Eidson  <beidson@apple.com>
    253
  • trunk/Source/WebCore/dom/Document.cpp

    r184816 r185012  
    27512751}
    27522752
     2753void Document::setTimerThrottlingEnabled(bool shouldThrottle)
     2754{
     2755    if (m_isTimerThrottlingEnabled == shouldThrottle)
     2756        return;
     2757
     2758    double previousInterval = timerAlignmentInterval();
     2759
     2760    m_isTimerThrottlingEnabled = shouldThrottle;
     2761
     2762    if (previousInterval != timerAlignmentInterval())
     2763        didChangeTimerAlignmentInterval();
     2764}
     2765
    27532766double Document::timerAlignmentInterval() const
    27542767{
     2768    if (m_isTimerThrottlingEnabled)
     2769        return DOMTimer::hiddenPageAlignmentInterval();
     2770
    27552771    Page* page = this->page();
    27562772    if (!page)
  • trunk/Source/WebCore/dom/Document.h

    r183998 r185012  
    432432    bool hidden() const;
    433433
     434    void setTimerThrottlingEnabled(bool);
     435    bool isTimerThrottlingEnabled() const { return m_isTimerThrottlingEnabled; }
     436
    434437#if ENABLE(CSP_NEXT)
    435438    DOMSecurityPolicy& securityPolicy();
     
    16891692
    16901693    bool m_hasStyleWithViewportUnits;
     1694    bool m_isTimerThrottlingEnabled { false };
    16911695
    16921696    HashSet<MediaProducer*> m_audioProducers;
  • trunk/Source/WebCore/page/DOMTimer.cpp

    r180801 r185012  
    508508double DOMTimer::alignedFireTime(double fireTime) const
    509509{
    510     double alignmentInterval = scriptExecutionContext()->timerAlignmentInterval();
    511     if (alignmentInterval) {
    512         double currentTime = monotonicallyIncreasingTime();
    513         if (fireTime <= currentTime)
    514             return fireTime;
    515 
    516         double alignedTime = ceil(fireTime / alignmentInterval) * alignmentInterval;
    517         return alignedTime;
    518     }
     510    if (double alignmentInterval = scriptExecutionContext()->timerAlignmentInterval())
     511        return ceil(fireTime / alignmentInterval) * alignmentInterval;
    519512
    520513    return fireTime;
  • trunk/Source/WebCore/page/FrameView.cpp

    r184947 r185012  
    18081808        frameView.resumeVisibleImageAnimations(visibleRect);
    18091809        frameView.updateThrottledDOMTimersState(visibleRect);
    1810         frameView.updateScriptedAnimationsThrottlingState(visibleRect);
     1810        frameView.updateScriptedAnimationsAndTimersThrottlingState(visibleRect);
    18111811    });
    18121812}
     
    21692169}
    21702170
    2171 void FrameView::updateScriptedAnimationsThrottlingState(const IntRect& visibleRect)
    2172 {
    2173 #if ENABLE(REQUEST_ANIMATION_FRAME)
     2171void FrameView::updateScriptedAnimationsAndTimersThrottlingState(const IntRect& visibleRect)
     2172{
    21742173    if (frame().isMainFrame())
    21752174        return;
     
    21772176    auto* document = frame().document();
    21782177    if (!document)
    2179         return;
    2180 
    2181     auto* scriptedAnimationController = document->scriptedAnimationController();
    2182     if (!scriptedAnimationController)
    21832178        return;
    21842179
     
    21862181    // they have a non-null ownerRenderer.
    21872182    bool shouldThrottle = !frame().ownerRenderer() || visibleRect.isEmpty();
    2188     scriptedAnimationController->setThrottled(shouldThrottle);
    2189 #else
    2190     UNUSED_PARAM(visibleRect);
     2183
     2184#if ENABLE(REQUEST_ANIMATION_FRAME)
     2185    if (auto* scriptedAnimationController = document->scriptedAnimationController())
     2186        scriptedAnimationController->setThrottled(shouldThrottle);
    21912187#endif
     2188
     2189    document->setTimerThrottlingEnabled(shouldThrottle);
    21922190}
    21932191
  • trunk/Source/WebCore/page/FrameView.h

    r184947 r185012  
    607607    void updateThrottledDOMTimersState(const IntRect& visibleRect);
    608608    void resumeVisibleImageAnimations(const IntRect& visibleRect);
    609     void updateScriptedAnimationsThrottlingState(const IntRect& visibleRect);
     609    void updateScriptedAnimationsAndTimersThrottlingState(const IntRect& visibleRect);
    610610
    611611    void updateLayerFlushThrottling();
  • trunk/Source/WebCore/testing/Internals.cpp

    r185006 r185012  
    800800}
    801801
     802bool Internals::areTimersThrottled() const
     803{
     804    return contextDocument()->isTimerThrottlingEnabled();
     805}
     806
    802807String Internals::visiblePlaceholder(Element* element)
    803808{
  • trunk/Source/WebCore/testing/Internals.h

    r184799 r185012  
    117117    bool isTimerThrottled(int timeoutId, ExceptionCode&);
    118118    bool isRequestAnimationFrameThrottled() const;
     119    bool areTimersThrottled() const;
    119120
    120121    // Spatial Navigation testing.
  • trunk/Source/WebCore/testing/Internals.idl

    r184799 r185012  
    286286
    287287    boolean isRequestAnimationFrameThrottled();
     288    boolean areTimersThrottled();
    288289
    289290    [RaisesException] void startTrackingStyleRecalcs();
Note: See TracChangeset for help on using the changeset viewer.