<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[212845] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/212845">212845</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2017-02-22 12:44:30 -0800 (Wed, 22 Feb 2017)</dd>
</dl>
<h3>Log Message</h3>
<pre>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:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsTestExpectations">trunk/LayoutTests/TestExpectations</a></li>
<li><a href="#trunkLayoutTestsfastdomtimerthrottlinghiddenpageexpectedtxt">trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastdomtimerthrottlinghiddenpagehtml">trunk/LayoutTests/fast/dom/timer-throttling-hidden-page.html</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorTestExpectations">trunk/LayoutTests/platform/ios-simulator/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastdomtimerthrottlinghiddenpagenonnestedexpectedtxt">trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-non-nested-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastdomtimerthrottlinghiddenpagenonnestedhtml">trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-non-nested.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (212844 => 212845)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-02-22 20:06:57 UTC (rev 212844)
+++ trunk/LayoutTests/ChangeLog        2017-02-22 20:44:30 UTC (rev 212845)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2017-02-22 Chris Dumez <cdumez@apple.com>
+
+ 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:
+
</ins><span class="cx"> 2017-02-22 Antti Koivisto <antti@apple.com>
</span><span class="cx">
</span><span class="cx"> REGRESSION(r207669): Crash after mutating selector text
</span></span></pre></div>
<a id="trunkLayoutTestsTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/TestExpectations (212844 => 212845)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/TestExpectations        2017-02-22 20:06:57 UTC (rev 212844)
+++ trunk/LayoutTests/TestExpectations        2017-02-22 20:44:30 UTC (rev 212845)
</span><span class="lines">@@ -109,8 +109,6 @@
</span><span class="cx"> # media/W3C/video/networkState/networkState_during_progress.html is flaky
</span><span class="cx"> webkit.org/b/76280 media/W3C/video/networkState/networkState_during_progress.html [ Pass Failure ]
</span><span class="cx">
</span><del>-webkit.org/b/118301 fast/dom/timer-throttling-hidden-page.html [ Skip ]
-
</del><span class="cx"> # This test will run slowly in debug mode, but is plenty fast in release.
</span><span class="cx"> [ Debug ] js/slow-stress/emscripten-memops.html [ Skip ]
</span><span class="cx">
</span></span></pre></div>
<a id="trunkLayoutTestsfastdomtimerthrottlinghiddenpageexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-expected.txt (212844 => 212845)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -3,12 +3,14 @@
</span><span class="cx"> On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
</span><span class="cx">
</span><span class="cx">
</span><del>-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
</del><ins>+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
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx">
</span><span class="cx"> TEST COMPLETE
</span><del>-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.
</del><ins>+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.
</ins></span></pre></div>
<a id="trunkLayoutTestsfastdomtimerthrottlinghiddenpagenonnestedexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-non-nested-expected.txt (0 => 212845)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+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
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastdomtimerthrottlinghiddenpagenonnestedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/dom/timer-throttling-hidden-page-non-nested.html (0 => 212845)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+<html>
+<head>
+ <script src="../../resources/js-test-pre.js"></script>
+ <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="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsfastdomtimerthrottlinghiddenpagehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/dom/timer-throttling-hidden-page.html (212844 => 212845)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -9,26 +9,17 @@
</span><span class="cx"> var timerCount = 0;
</span><span class="cx"> var firstTimerWhileHidden = true;
</span><span class="cx"> var isPageVisible = true;
</span><del>- var timeoutInterval = 100;
</del><ins>+ var timeoutInterval = 10;
</ins><span class="cx"> var tolerance = 20;
</span><del>- var timerAlignmentInterval = 1000;
</del><ins>+ var maxNestingLevel = 5;
</ins><span class="cx">
</span><span class="cx"> function testTimer()
</span><span class="cx"> {
</span><span class="cx"> var date = new Date();
</span><span class="cx"> var time = date.getTime();
</span><del>- 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);
- }
</del><ins>+ if (!isPageVisible && timerCount >= maxNestingLevel) {
+ timerIntervalWhilePageHidden = time - previousTime;
+ shouldBeTrue("timerIntervalWhilePageHidden > (timeoutInterval + tolerance)");
</ins><span class="cx"> } else {
</span><span class="cx"> timerIntervalWhilePageVisible = time - previousTime;
</span><span class="cx"> shouldBeCloseTo("timerIntervalWhilePageVisible", timeoutInterval, tolerance);
</span><span class="lines">@@ -40,10 +31,10 @@
</span><span class="cx"> if (timerCount == 1) {
</span><span class="cx"> testRunner.setPageVisibility("hidden");
</span><span class="cx"> isPageVisible = false;
</span><del>- } else if (timerCount == 3) {
</del><ins>+ } else if (timerCount == maxNestingLevel + 1) {
</ins><span class="cx"> testRunner.resetPageVisibility();
</span><span class="cx"> isPageVisible = true;
</span><del>- } else if (timerCount >= 4){
</del><ins>+ } else if (timerCount > maxNestingLevel + 1){
</ins><span class="cx"> finishJSTest();
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="lines">@@ -62,8 +53,6 @@
</span><span class="cx"> for (var i = 0; i < timeoutIntervalSpans.length; i++)
</span><span class="cx"> timeoutIntervalSpans[i].innerText = timeoutInterval;
</span><span class="cx">
</span><del>- document.getElementById('alignmentInterval').innerText = timerAlignmentInterval / 1000;
-
</del><span class="cx"> testRunner.dumpAsText();
</span><span class="cx"> setTimeout(testTimer, timeoutInterval);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (212844 => 212845)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -300,6 +300,8 @@
</span><span class="cx"> fast/events/mouse-force-up.html [ Skip ]
</span><span class="cx">
</span><span class="cx"> # testRunner.setPageVisibility is not implemented for iOS
</span><ins>+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 ]
</ins><span class="cx"> webkit.org/b/165799 fast/events/page-visibility-onvisibilitychange.html [ Skip ]
</span><span class="cx"> webkit.org/b/165799 svg/animations/animations-paused-page-non-visible.html [ Skip ]
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (212844 => 212845)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2017-02-22 Chris Dumez <cdumez@apple.com>
+
+ 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):
+
</ins><span class="cx"> 2017-02-22 Eric Carlson <eric.carlson@apple.com>
</span><span class="cx">
</span><span class="cx"> [MediaStream iOS] Respond to capture interruptions and notifications
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (212844 => 212845)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -2847,9 +2847,11 @@
</span><span class="cx"> std::chrono::milliseconds Document::timerAlignmentInterval(bool hasReachedMaxNestingLevel) const
</span><span class="cx"> {
</span><span class="cx"> auto alignmentInterval = ScriptExecutionContext::timerAlignmentInterval(hasReachedMaxNestingLevel);
</span><ins>+ if (!hasReachedMaxNestingLevel)
+ return alignmentInterval;
</ins><span class="cx">
</span><span class="cx"> // Apply Document-level DOMTimer throttling only if timers have reached their maximum nesting level as the Page may still be visible.
</span><del>- if (m_isTimerThrottlingEnabled && hasReachedMaxNestingLevel)
</del><ins>+ if (m_isTimerThrottlingEnabled)
</ins><span class="cx"> alignmentInterval = std::max(alignmentInterval, DOMTimer::hiddenPageAlignmentInterval());
</span><span class="cx">
</span><span class="cx"> if (Page* page = this->page())
</span></span></pre>
</div>
</div>
</body>
</html>