Title: [212845] trunk
Revision
212845
Author
[email protected]
Date
2017-02-22 12:44:30 -0800 (Wed, 22 Feb 2017)

Log Message

Do not aggressively throttle DOM timers until they've reached their max nesting level
https://bugs.webkit.org/show_bug.cgi?id=168700
<rdar://problem/29808005>

Reviewed by Simon Fraser.

Source/WebCore:

Do not aggressively throttle DOM timers until they've actually areached their max
nesting level (5). This overly aggressive throttling of non-nested timers is what
was causing Google Maps to use 100% CPU in background tabs for several minutes.

Test: fast/dom/timer-throttling-hidden-page-non-nested.html

* dom/Document.cpp:
(WebCore::Document::timerAlignmentInterval):

LayoutTests:

Add layout test coverage.

* TestExpectations:
* fast/dom/timer-throttling-hidden-page-expected.txt:
* fast/dom/timer-throttling-hidden-page-non-nested-expected.txt: Added.
* fast/dom/timer-throttling-hidden-page-non-nested.html: Added.
* fast/dom/timer-throttling-hidden-page.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (212844 => 212845)


--- trunk/LayoutTests/ChangeLog	2017-02-22 20:06:57 UTC (rev 212844)
+++ trunk/LayoutTests/ChangeLog	2017-02-22 20:44:30 UTC (rev 212845)
@@ -1,3 +1,19 @@
+2017-02-22  Chris Dumez  <[email protected]>
+
+        Do not aggressively throttle DOM timers until they've reached their max nesting level
+        https://bugs.webkit.org/show_bug.cgi?id=168700
+        <rdar://problem/29808005>
+
+        Reviewed by Simon Fraser.
+
+        Add layout test coverage.
+
+        * TestExpectations:
+        * fast/dom/timer-throttling-hidden-page-expected.txt:
+        * fast/dom/timer-throttling-hidden-page-non-nested-expected.txt: Added.
+        * fast/dom/timer-throttling-hidden-page-non-nested.html: Added.
+        * fast/dom/timer-throttling-hidden-page.html:
+
 2017-02-22  Antti Koivisto  <[email protected]>
 
         REGRESSION(r207669): Crash after mutating selector text

Modified: trunk/LayoutTests/TestExpectations (212844 => 212845)


--- trunk/LayoutTests/TestExpectations	2017-02-22 20:06:57 UTC (rev 212844)
+++ trunk/LayoutTests/TestExpectations	2017-02-22 20:44:30 UTC (rev 212845)
@@ -109,8 +109,6 @@
 # media/W3C/video/networkState/networkState_during_progress.html is flaky
 webkit.org/b/76280 media/W3C/video/networkState/networkState_during_progress.html [ Pass Failure ]
 
-webkit.org/b/118301 fast/dom/timer-throttling-hidden-page.html [ Skip ]
-
 # This test will run slowly in debug mode, but is plenty fast in release.
 [ Debug ] js/slow-stress/emscripten-memops.html [ Skip ]
 

Modified: trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-expected.txt (212844 => 212845)


--- trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-expected.txt	2017-02-22 20:06:57 UTC (rev 212844)
+++ trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-expected.txt	2017-02-22 20:44:30 UTC (rev 212845)
@@ -3,12 +3,14 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS timerIntervalWhilePageVisible is within 20 of 100
-PASS firstTimerIntervalWhilePageHidden is >= 80
-PASS firstTimerIntervalWhilePageHidden <= 1120 is true
-PASS timerIntervalWhilePageHidden is within 20 of 1000
-PASS timerIntervalWhilePageVisible is within 20 of 100
+PASS timerIntervalWhilePageVisible is within 20 of 10
+PASS timerIntervalWhilePageVisible is within 20 of 10
+PASS timerIntervalWhilePageVisible is within 20 of 10
+PASS timerIntervalWhilePageVisible is within 20 of 10
+PASS timerIntervalWhilePageVisible is within 20 of 10
+PASS timerIntervalWhilePageHidden > (timeoutInterval + tolerance) is true
+PASS timerIntervalWhilePageVisible is within 20 of 10
 PASS successfullyParsed is true
 
 TEST COMPLETE
-This test measures the time taken to fire a 100ms DOM Timer when the page visibility is set to "visible", "hidden" and then back to "visible". Due to hidden page timer throttling, the timer should fire close to 1s when page is hidden. And it should fire close to 100ms, when the page is visible.
+This test measures the time taken to fire a 10ms DOM Timer when the page visibility is set to "visible", "hidden" and then back to "visible". Due to hidden page timer throttling, the timer should fire close to s when page is hidden. And it should fire close to 10ms, when the page is visible.

Added: trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-non-nested-expected.txt (0 => 212845)


--- trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-non-nested-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-non-nested-expected.txt	2017-02-22 20:44:30 UTC (rev 212845)
@@ -0,0 +1,13 @@
+Tests that DOM timers on hidden pages that have not reached max nesting level are not throttled.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS timerIntervalWhilePageVisible is within 20 of 10
+PASS timerIntervalWhilePageVisible is within 20 of 10
+PASS timerIntervalWhilePageVisible is within 20 of 10
+PASS timerIntervalWhilePageVisible is within 20 of 10
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-non-nested.html (0 => 212845)


--- trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-non-nested.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-non-nested.html	2017-02-22 20:44:30 UTC (rev 212845)
@@ -0,0 +1,58 @@
+<html>
+<head>
+    <script src=""
+    <script>
+        description('Tests that DOM timers on hidden pages that have not reached max nesting level are not throttled.');
+
+        var jsTestIsAsync = true;
+        var previousTime = new Date().getTime();
+        var timerCount = 0;
+        var firstTimerWhileHidden = true;
+        var isPageVisible = true;
+        var timeoutInterval = 10;
+        var tolerance = 20;
+
+        function testTimer()
+        {
+            var date = new Date();
+            var time = date.getTime();
+            timerIntervalWhilePageVisible = time - previousTime;
+            shouldBeCloseTo("timerIntervalWhilePageVisible", timeoutInterval, tolerance);
+
+            timerCount++;
+            previousTime = time;
+
+            if (timerCount == 1) {
+                testRunner.setPageVisibility("hidden");
+                isPageVisible = false;
+            } else if (timerCount == 3) {
+                testRunner.resetPageVisibility();
+                isPageVisible = true;
+            } else if (timerCount > 3){
+                finishJSTest();
+                return;
+            }
+            setTimeout(testTimer, timeoutInterval);
+        }
+
+        function runTest()
+        {
+            if (!window.testRunner) {
+                debug('This test requires testRunner');
+                return;
+            }
+            testRunner.overridePreference("WebKitHiddenPageDOMTimerThrottlingEnabled", 1);
+
+            var timeoutIntervalSpans = document.getElementsByClassName('timeoutInterval');
+            for (var i = 0; i < timeoutIntervalSpans.length; i++)
+                timeoutIntervalSpans[i].innerText = timeoutInterval;
+
+            testRunner.dumpAsText();
+            setTimeout(testTimer, timeoutInterval);
+        }
+    </script>
+</head>
+<body _onload_="runTest()">
+    <script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/fast/dom/timer-throttling-hidden-page.html (212844 => 212845)


--- trunk/LayoutTests/fast/dom/timer-throttling-hidden-page.html	2017-02-22 20:06:57 UTC (rev 212844)
+++ trunk/LayoutTests/fast/dom/timer-throttling-hidden-page.html	2017-02-22 20:44:30 UTC (rev 212845)
@@ -9,26 +9,17 @@
         var timerCount = 0;
         var firstTimerWhileHidden = true;
         var isPageVisible = true;
-        var timeoutInterval = 100;
+        var timeoutInterval = 10;
         var tolerance = 20;
-        var timerAlignmentInterval = 1000;
+        var maxNestingLevel = 5;
 
         function testTimer()
         {
             var date = new Date();
             var time = date.getTime();
-            if (!isPageVisible) {
-                if (firstTimerWhileHidden) {
-                    firstTimerIntervalWhilePageHidden = time - previousTime;
-                    var minValue = timeoutInterval - tolerance;
-                    shouldBeGreaterThanOrEqual("firstTimerIntervalWhilePageHidden", minValue.toString());
-                    var maxValue = timeoutInterval + timerAlignmentInterval + tolerance;
-                    shouldBeTrue("firstTimerIntervalWhilePageHidden <= " + maxValue);
-                    firstTimerWhileHidden = false;
-                } else {
-                    timerIntervalWhilePageHidden = time - previousTime;
-                    shouldBeCloseTo("timerIntervalWhilePageHidden", timerAlignmentInterval, tolerance);
-                }
+            if (!isPageVisible && timerCount >= maxNestingLevel) {
+                timerIntervalWhilePageHidden = time - previousTime;
+                shouldBeTrue("timerIntervalWhilePageHidden > (timeoutInterval + tolerance)");
             } else {
                 timerIntervalWhilePageVisible = time - previousTime;
                 shouldBeCloseTo("timerIntervalWhilePageVisible", timeoutInterval, tolerance);
@@ -40,10 +31,10 @@
             if (timerCount == 1) {
                 testRunner.setPageVisibility("hidden");
                 isPageVisible = false;
-            } else if (timerCount == 3) {
+            } else if (timerCount == maxNestingLevel + 1) {
                 testRunner.resetPageVisibility();
                 isPageVisible = true;
-            } else if (timerCount >= 4){
+            } else if (timerCount > maxNestingLevel + 1){
                 finishJSTest();
                 return;
             }
@@ -62,8 +53,6 @@
             for (var i = 0; i < timeoutIntervalSpans.length; i++)
                 timeoutIntervalSpans[i].innerText = timeoutInterval;
 
-            document.getElementById('alignmentInterval').innerText = timerAlignmentInterval / 1000;
-
             testRunner.dumpAsText();
             setTimeout(testTimer, timeoutInterval);
         }

Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (212844 => 212845)


--- trunk/LayoutTests/platform/ios-simulator/TestExpectations	2017-02-22 20:06:57 UTC (rev 212844)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations	2017-02-22 20:44:30 UTC (rev 212845)
@@ -300,6 +300,8 @@
 fast/events/mouse-force-up.html [ Skip ]
 
 # testRunner.setPageVisibility is not implemented for iOS
+webkit.org/b/165799 fast/dom/timer-throttling-hidden-page.html [ Skip ]
+webkit.org/b/165799 fast/dom/timer-throttling-hidden-page-non-nested.html [ Skip ]
 webkit.org/b/165799 fast/events/page-visibility-onvisibilitychange.html [ Skip ]
 webkit.org/b/165799 svg/animations/animations-paused-page-non-visible.html [ Skip ]
 

Modified: trunk/Source/WebCore/ChangeLog (212844 => 212845)


--- trunk/Source/WebCore/ChangeLog	2017-02-22 20:06:57 UTC (rev 212844)
+++ trunk/Source/WebCore/ChangeLog	2017-02-22 20:44:30 UTC (rev 212845)
@@ -1,3 +1,20 @@
+2017-02-22  Chris Dumez  <[email protected]>
+
+        Do not aggressively throttle DOM timers until they've reached their max nesting level
+        https://bugs.webkit.org/show_bug.cgi?id=168700
+        <rdar://problem/29808005>
+
+        Reviewed by Simon Fraser.
+
+        Do not aggressively throttle DOM timers until they've actually areached their max
+        nesting level (5). This overly aggressive throttling of non-nested timers is what
+        was causing Google Maps to use 100% CPU in background tabs for several minutes.
+
+        Test: fast/dom/timer-throttling-hidden-page-non-nested.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::timerAlignmentInterval):
+
 2017-02-22  Eric Carlson  <[email protected]>
 
         [MediaStream iOS] Respond to capture interruptions and notifications

Modified: trunk/Source/WebCore/dom/Document.cpp (212844 => 212845)


--- trunk/Source/WebCore/dom/Document.cpp	2017-02-22 20:06:57 UTC (rev 212844)
+++ trunk/Source/WebCore/dom/Document.cpp	2017-02-22 20:44:30 UTC (rev 212845)
@@ -2847,9 +2847,11 @@
 std::chrono::milliseconds Document::timerAlignmentInterval(bool hasReachedMaxNestingLevel) const
 {
     auto alignmentInterval = ScriptExecutionContext::timerAlignmentInterval(hasReachedMaxNestingLevel);
+    if (!hasReachedMaxNestingLevel)
+        return alignmentInterval;
 
     // Apply Document-level DOMTimer throttling only if timers have reached their maximum nesting level as the Page may still be visible.
-    if (m_isTimerThrottlingEnabled && hasReachedMaxNestingLevel)
+    if (m_isTimerThrottlingEnabled)
         alignmentInterval = std::max(alignmentInterval, DOMTimer::hiddenPageAlignmentInterval());
 
     if (Page* page = this->page())
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to