- Revision
- 197213
- Author
- [email protected]
- Date
- 2016-02-26 15:26:36 -0800 (Fri, 26 Feb 2016)
Log Message
Page TimerAlignmentIntervalIncrease mechanism should have upper limit
https://bugs.webkit.org/show_bug.cgi?id=154744
Reviewed by Geoff Garen.
There would be diminishing returns from throttling timers in background pages infinitely.
Add a heuristic to limit appropriately.
Source/WebCore:
Keep track of the current limit, and make the increase time take this into account.
* page/Page.cpp:
(WebCore::Page::setTimerThrottlingEnabled):
- When timer throttling is disabled visit all timers to resume.
(WebCore::Page::setTimerAlignmentIntervalIncreaseLimit):
- Track the maximum alignment interval, and call setDOMTimerAlignmentInterval
to ensure m_timerAlignmentInterval is updated in accordance with the new limit.
(WebCore::Page::setDOMTimerAlignmentInterval):
- When the timer alignemnt interval changes update the increase timer.
(WebCore::Page::timerAlignmentIntervalIncreaseTimerFired):
- Apply limit.
* page/Page.h:
(WebCore::Page::timerThrottlingEnabled):
- Accessor for readability.
Source/WebKit2:
The flow of data here is WebPageProxy informs WebProcessPool of the number of pages
participating in this mechanism, WebProcessPool computes an apropriate limit and pushes
this out to the WebProcesses, which in turn update each of their pages.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::WebPageProxy):
- Call updateHidenPageThrottingAutoIncreases on creation.
(WebKit::WebPageProxy::updateHidenPageThrottingAutoIncreases):
- If increasing timer throttling is enabled increment the counter on WebProcessPool.
(WebKit::WebPageProxy::preferencesDidChange):
- Call updateHidenPageThrottingAutoIncreases on preferences change.
* UIProcess/WebPageProxy.h:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::WebProcessPool):
- initialize new RefCounter.
(WebKit::WebProcessPool::updateHidenPageThrottingAutoIncreaseLimit):
- When count of participating pages changes, update the limit.
* UIProcess/WebProcessPool.h:
* WebProcess/WebPage/WebPage.h:
(WebKit::WebPage::setHiddenPageTimerThrottlingIncreaseLimit):
- Propagate limit to WebCore::Page.
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::setHiddenPageTimerThrottlingIncreaseLimit):
- Propagate limit to WebPages.
* WebProcess/WebProcess.h:
* WebProcess/WebProcess.messages.in:
- Added new message.
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (197212 => 197213)
--- trunk/Source/WebCore/ChangeLog 2016-02-26 23:09:08 UTC (rev 197212)
+++ trunk/Source/WebCore/ChangeLog 2016-02-26 23:26:36 UTC (rev 197213)
@@ -1,3 +1,29 @@
+2016-02-26 Gavin Barraclough <[email protected]>
+
+ Page TimerAlignmentIntervalIncrease mechanism should have upper limit
+ https://bugs.webkit.org/show_bug.cgi?id=154744
+
+ Reviewed by Geoff Garen.
+
+ There would be diminishing returns from throttling timers in background pages infinitely.
+ Add a heuristic to limit appropriately.
+
+ Keep track of the current limit, and make the increase time take this into account.
+
+ * page/Page.cpp:
+ (WebCore::Page::setTimerThrottlingEnabled):
+ - When timer throttling is disabled visit all timers to resume.
+ (WebCore::Page::setTimerAlignmentIntervalIncreaseLimit):
+ - Track the maximum alignment interval, and call setDOMTimerAlignmentInterval
+ to ensure m_timerAlignmentInterval is updated in accordance with the new limit.
+ (WebCore::Page::setDOMTimerAlignmentInterval):
+ - When the timer alignemnt interval changes update the increase timer.
+ (WebCore::Page::timerAlignmentIntervalIncreaseTimerFired):
+ - Apply limit.
+ * page/Page.h:
+ (WebCore::Page::timerThrottlingEnabled):
+ - Accessor for readability.
+
2016-02-26 Beth Dakin <[email protected]>
Attempted build fix.
Modified: trunk/Source/WebCore/page/Page.cpp (197212 => 197213)
--- trunk/Source/WebCore/page/Page.cpp 2016-02-26 23:09:08 UTC (rev 197212)
+++ trunk/Source/WebCore/page/Page.cpp 2016-02-26 23:26:36 UTC (rev 197213)
@@ -1167,48 +1167,59 @@
if (!m_settings->hiddenPageDOMTimerThrottlingEnabled())
enabled = false;
- if (enabled == !!m_timerThrottlingEnabledTime)
+ if (enabled == timerThrottlingEnabled())
return;
m_timerThrottlingEnabledTime = enabled ? monotonicallyIncreasingTime() : Optional<double>();
setDOMTimerAlignmentInterval(enabled ? DOMTimer::hiddenPageAlignmentInterval() : DOMTimer::defaultAlignmentInterval());
+
+ if (enabled)
+ return;
+
+ // If throttling was disabled, release all throttled timers.
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (auto* document = frame->document())
+ document->didChangeTimerAlignmentInterval();
+ }
}
+void Page::setTimerAlignmentIntervalIncreaseLimit(std::chrono::milliseconds limit)
+{
+ // FIXME: std::chrono-ify all timer allignment related code.
+ m_timerAlignmentIntervalIncreaseLimit = limit.count() * 0.001;
+
+ if (!timerThrottlingEnabled())
+ return;
+
+ // If (m_timerAlignmentIntervalIncreaseLimit < m_timerAlignmentInterval) then we need
+ // to update m_timerAlignmentInterval, if greater then need to restart the increase timer.
+ setDOMTimerAlignmentInterval(std::min(m_timerAlignmentIntervalIncreaseLimit, m_timerAlignmentInterval));
+}
+
void Page::setDOMTimerAlignmentInterval(double alignmentInterval)
{
- // If the new alignmentInterval is shorter than the one presently in effect we need to update
- // existing timers (e.g. when a hidden page becomes visible throttled timers must be unthrottled).
- // However when lengthening the alignment interval, no need to update existing timers. Not doing
- // so means that timers scheduled while the page is visible get to fire accurately (repeating
- // timers will be throttled on the next timer fire).
- bool shouldRescheduleExistingTimers = alignmentInterval < m_timerAlignmentInterval;
-
m_timerAlignmentInterval = alignmentInterval;
- if (shouldRescheduleExistingTimers) {
- for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
- if (auto* document = frame->document())
- document->didChangeTimerAlignmentInterval();
- }
- }
-
- // If throttling is enabled and auto-increasing of throttling is enabled then arm the timer to
- // consider an increase. Time to wait between increases is equal to the current throttle time.
- // Since alinment interval increases exponentially, time between steps is exponential too.
- if (m_timerThrottlingEnabledTime && m_settings->hiddenPageDOMTimerThrottlingAutoIncreases())
+ // If throttling is enabled, auto-increasing of throttling is enabled, and the auto-increase
+ // limit has not yet been reached, and then arm the timer to consider an increase. Time to wait
+ // between increases is equal to the current throttle time. Since alinment interval increases
+ // exponentially, time between steps is exponential too.
+ if (!timerThrottlingEnabled() || !m_settings->hiddenPageDOMTimerThrottlingAutoIncreases()
+ || m_timerAlignmentInterval >= m_timerAlignmentIntervalIncreaseLimit)
+ m_timerAlignmentIntervalIncreaseTimer.stop();
+ else if (!m_timerAlignmentIntervalIncreaseTimer.isActive())
m_timerAlignmentIntervalIncreaseTimer.startOneShot(m_timerAlignmentInterval);
- else
- m_timerAlignmentIntervalIncreaseTimer.stop();
}
void Page::timerAlignmentIntervalIncreaseTimerFired()
{
- ASSERT(m_timerThrottlingEnabledTime && m_settings->hiddenPageDOMTimerThrottlingAutoIncreases());
+ ASSERT(timerThrottlingEnabled() && m_settings->hiddenPageDOMTimerThrottlingAutoIncreases());
+ ASSERT(m_timerAlignmentInterval < m_timerAlignmentIntervalIncreaseLimit);
- // Alignment interval is increased to equal the time the page has been throttled.
+ // Alignment interval is increased to equal the time the page has been throttled, to a limit.
double throttledDuration = monotonicallyIncreasingTime() - m_timerThrottlingEnabledTime.value();
double alignmentInterval = std::max(m_timerAlignmentInterval, throttledDuration);
- setDOMTimerAlignmentInterval(alignmentInterval);
+ setDOMTimerAlignmentInterval(std::min(alignmentInterval, m_timerAlignmentIntervalIncreaseLimit));
}
void Page::dnsPrefetchingStateChanged()
Modified: trunk/Source/WebCore/page/Page.h (197212 => 197213)
--- trunk/Source/WebCore/page/Page.h 2016-02-26 23:09:08 UTC (rev 197212)
+++ trunk/Source/WebCore/page/Page.h 2016-02-26 23:26:36 UTC (rev 197213)
@@ -499,6 +499,8 @@
void setShowAllPlugins(bool showAll) { m_showAllPlugins = showAll; }
bool showAllPlugins() const;
+ WEBCORE_EXPORT void setTimerAlignmentIntervalIncreaseLimit(std::chrono::milliseconds);
+
private:
WEBCORE_EXPORT void initGroup();
@@ -525,6 +527,7 @@
void setTimerThrottlingEnabled(bool);
void setDOMTimerAlignmentInterval(double);
void timerAlignmentIntervalIncreaseTimerFired();
+ bool timerThrottlingEnabled() const { return !!m_timerThrottlingEnabledTime; }
const std::unique_ptr<Chrome> m_chrome;
const std::unique_ptr<DragCaretController> m_dragCaretController;
@@ -613,6 +616,7 @@
Optional<double> m_timerThrottlingEnabledTime;
double m_timerAlignmentInterval;
Timer m_timerAlignmentIntervalIncreaseTimer;
+ double m_timerAlignmentIntervalIncreaseLimit { 0 };
bool m_isEditable;
bool m_isPrerender;
Modified: trunk/Source/WebKit2/ChangeLog (197212 => 197213)
--- trunk/Source/WebKit2/ChangeLog 2016-02-26 23:09:08 UTC (rev 197212)
+++ trunk/Source/WebKit2/ChangeLog 2016-02-26 23:26:36 UTC (rev 197213)
@@ -1,3 +1,41 @@
+2016-02-26 Gavin Barraclough <[email protected]>
+
+ Page TimerAlignmentIntervalIncrease mechanism should have upper limit
+ https://bugs.webkit.org/show_bug.cgi?id=154744
+
+ Reviewed by Geoff Garen.
+
+ There would be diminishing returns from throttling timers in background pages infinitely.
+ Add a heuristic to limit appropriately.
+
+ The flow of data here is WebPageProxy informs WebProcessPool of the number of pages
+ participating in this mechanism, WebProcessPool computes an apropriate limit and pushes
+ this out to the WebProcesses, which in turn update each of their pages.
+
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::WebPageProxy):
+ - Call updateHidenPageThrottingAutoIncreases on creation.
+ (WebKit::WebPageProxy::updateHidenPageThrottingAutoIncreases):
+ - If increasing timer throttling is enabled increment the counter on WebProcessPool.
+ (WebKit::WebPageProxy::preferencesDidChange):
+ - Call updateHidenPageThrottingAutoIncreases on preferences change.
+ * UIProcess/WebPageProxy.h:
+ * UIProcess/WebProcessPool.cpp:
+ (WebKit::WebProcessPool::WebProcessPool):
+ - initialize new RefCounter.
+ (WebKit::WebProcessPool::updateHidenPageThrottingAutoIncreaseLimit):
+ - When count of participating pages changes, update the limit.
+ * UIProcess/WebProcessPool.h:
+ * WebProcess/WebPage/WebPage.h:
+ (WebKit::WebPage::setHiddenPageTimerThrottlingIncreaseLimit):
+ - Propagate limit to WebCore::Page.
+ * WebProcess/WebProcess.cpp:
+ (WebKit::WebProcess::setHiddenPageTimerThrottlingIncreaseLimit):
+ - Propagate limit to WebPages.
+ * WebProcess/WebProcess.h:
+ * WebProcess/WebProcess.messages.in:
+ - Added new message.
+
2016-02-26 Beth Dakin <[email protected]>
Attempted build fix.
Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (197212 => 197213)
--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp 2016-02-26 23:09:08 UTC (rev 197212)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp 2016-02-26 23:26:36 UTC (rev 197213)
@@ -448,6 +448,7 @@
updateViewState();
updateActivityToken();
updateProccessSuppressionState();
+ updateHiddenPageThrottlingAutoIncreases();
#if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
m_layerHostingMode = m_viewState & ViewState::IsInWindow ? m_pageClient.viewLayerHostingMode() : LayerHostingMode::OutOfProcess;
@@ -1491,6 +1492,14 @@
m_preventProcessSuppressionCount = m_process->processPool().processSuppressionDisabledForPageCount();
}
+void WebPageProxy::updateHiddenPageThrottlingAutoIncreases()
+{
+ if (!m_preferences->hiddenPageDOMTimerThrottlingAutoIncreases())
+ m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = nullptr;
+ else if (!m_hiddenPageDOMTimerThrottlingAutoIncreasesCount)
+ m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = m_process->processPool().hiddenPageThrottlingAutoIncreasesCount();
+}
+
void WebPageProxy::layerHostingModeDidChange()
{
if (!isValid())
@@ -2782,6 +2791,7 @@
#endif
updateProccessSuppressionState();
+ updateHiddenPageThrottlingAutoIncreases();
m_pageClient.preferencesDidChange();
Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (197212 => 197213)
--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h 2016-02-26 23:09:08 UTC (rev 197212)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h 2016-02-26 23:26:36 UTC (rev 197213)
@@ -171,6 +171,9 @@
namespace WebKit {
+enum HiddenPageThrottlingAutoIncreasesCounterType { };
+typedef RefCounter<HiddenPageThrottlingAutoIncreasesCounterType> HiddenPageThrottlingAutoIncreasesCounter;
+
class CertificateInfo;
class NativeWebGestureEvent;
class NativeWebKeyboardEvent;
@@ -1090,6 +1093,7 @@
void updateViewState(WebCore::ViewState::Flags flagsToUpdate = WebCore::ViewState::AllFlags);
void updateActivityToken();
void updateProccessSuppressionState();
+ void updateHiddenPageThrottlingAutoIncreases();
enum class ResetStateReason {
PageInvalidated,
@@ -1764,6 +1768,7 @@
#endif
UserObservablePageToken m_pageIsUserObservableCount;
ProcessSuppressionDisabledToken m_preventProcessSuppressionCount;
+ HiddenPageThrottlingAutoIncreasesCounter::Token m_hiddenPageDOMTimerThrottlingAutoIncreasesCount;
WebCore::ScrollPinningBehavior m_scrollPinningBehavior;
WTF::Optional<WebCore::ScrollbarOverlayStyle> m_scrollbarOverlayStyle;
Modified: trunk/Source/WebKit2/UIProcess/WebProcessPool.cpp (197212 => 197213)
--- trunk/Source/WebKit2/UIProcess/WebProcessPool.cpp 2016-02-26 23:09:08 UTC (rev 197212)
+++ trunk/Source/WebKit2/UIProcess/WebProcessPool.cpp 2016-02-26 23:26:36 UTC (rev 197213)
@@ -160,6 +160,7 @@
, m_memoryCacheDisabled(false)
, m_userObservablePageCounter([this](UserObservablePageCounter::Event) { updateProcessSuppressionState(); })
, m_processSuppressionDisabledForPageCounter([this](ProcessSuppressionDisabledCounter::Event) { updateProcessSuppressionState(); })
+ , m_hiddenPageThrottlingAutoIncreasesCounter([this](HiddenPageThrottlingAutoIncreasesCounter::Event) { updateHiddenPageThrottlingAutoIncreaseLimit(); })
{
for (auto& scheme : m_configuration->alwaysRevalidatedURLSchemes())
m_schemesToRegisterAsAlwaysRevalidated.add(scheme);
@@ -1321,4 +1322,15 @@
}
}
+void WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit()
+{
+ // We're estimating an upper bound for a set of background timer fires for a page to be 200ms
+ // (including all timer fires, all paging-in, and any resulting GC). To ensure this does not
+ // result in more than 1% CPU load allow for one timer fire per 100x this duration.
+ static int maximumTimerThrottlePerPageInMS = 200 * 100;
+
+ int limitInMilliseconds = maximumTimerThrottlePerPageInMS * m_hiddenPageThrottlingAutoIncreasesCounter.value();
+ sendToAllProcesses(Messages::WebProcess::SetHiddenPageTimerThrottlingIncreaseLimit(limitInMilliseconds));
+}
+
} // namespace WebKit
Modified: trunk/Source/WebKit2/UIProcess/WebProcessPool.h (197212 => 197213)
--- trunk/Source/WebKit2/UIProcess/WebProcessPool.h 2016-02-26 23:09:08 UTC (rev 197212)
+++ trunk/Source/WebKit2/UIProcess/WebProcessPool.h 2016-02-26 23:26:36 UTC (rev 197213)
@@ -333,6 +333,8 @@
void updateProcessSuppressionState() const { }
#endif
+ void updateHiddenPageThrottlingAutoIncreaseLimit();
+
void setMemoryCacheDisabled(bool);
void setFontWhitelist(API::Array*);
@@ -346,6 +348,11 @@
return m_processSuppressionDisabledForPageCounter.count();
}
+ HiddenPageThrottlingAutoIncreasesCounter::Token hiddenPageThrottlingAutoIncreasesCount()
+ {
+ return m_hiddenPageThrottlingAutoIncreasesCounter.count();
+ }
+
// FIXME: Move these to API::WebsiteDataStore.
static String legacyPlatformDefaultLocalStorageDirectory();
static String legacyPlatformDefaultIndexedDBDatabaseDirectory();
@@ -509,6 +516,7 @@
UserObservablePageCounter m_userObservablePageCounter;
ProcessSuppressionDisabledCounter m_processSuppressionDisabledForPageCounter;
+ HiddenPageThrottlingAutoIncreasesCounter m_hiddenPageThrottlingAutoIncreasesCounter;
#if PLATFORM(COCOA)
RetainPtr<NSMutableDictionary> m_bundleParameters;
Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (197212 => 197213)
--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h 2016-02-26 23:09:08 UTC (rev 197212)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h 2016-02-26 23:26:36 UTC (rev 197213)
@@ -289,6 +289,11 @@
void setActivePopupMenu(WebPopupMenu*);
+ void setHiddenPageTimerThrottlingIncreaseLimit(std::chrono::milliseconds limit)
+ {
+ m_page->setTimerAlignmentIntervalIncreaseLimit(limit);
+ }
+
#if ENABLE(INPUT_TYPE_COLOR)
WebColorChooser* activeColorChooser() const { return m_activeColorChooser; }
void setActiveColorChooser(WebColorChooser*);
Modified: trunk/Source/WebKit2/WebProcess/WebProcess.cpp (197212 => 197213)
--- trunk/Source/WebKit2/WebProcess/WebProcess.cpp 2016-02-26 23:09:08 UTC (rev 197212)
+++ trunk/Source/WebKit2/WebProcess/WebProcess.cpp 2016-02-26 23:26:36 UTC (rev 197213)
@@ -1150,6 +1150,12 @@
parentProcessConnection()->send(Messages::WebProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
}
+void WebProcess::setHiddenPageTimerThrottlingIncreaseLimit(int milliseconds)
+{
+ for (auto& page : m_pageMap.values())
+ page->setHiddenPageTimerThrottlingIncreaseLimit(std::chrono::milliseconds(milliseconds));
+}
+
#if !PLATFORM(COCOA)
void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&)
{
Modified: trunk/Source/WebKit2/WebProcess/WebProcess.h (197212 => 197213)
--- trunk/Source/WebKit2/WebProcess/WebProcess.h 2016-02-26 23:09:08 UTC (rev 197212)
+++ trunk/Source/WebKit2/WebProcess/WebProcess.h 2016-02-26 23:26:36 UTC (rev 197213)
@@ -176,6 +176,8 @@
void updateActivePages();
+ void setHiddenPageTimerThrottlingIncreaseLimit(int milliseconds);
+
void processWillSuspendImminently(bool& handled);
void prepareToSuspend();
void cancelPrepareToSuspend();
Modified: trunk/Source/WebKit2/WebProcess/WebProcess.messages.in (197212 => 197213)
--- trunk/Source/WebKit2/WebProcess/WebProcess.messages.in 2016-02-26 23:09:08 UTC (rev 197212)
+++ trunk/Source/WebKit2/WebProcess/WebProcess.messages.in 2016-02-26 23:26:36 UTC (rev 197213)
@@ -79,6 +79,7 @@
DeleteWebsiteData(WebCore::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID)
DeleteWebsiteDataForOrigins(WebCore::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> websiteDataTypes, Vector<WebCore::SecurityOriginData> origins, uint64_t callbackID)
+ SetHiddenPageTimerThrottlingIncreaseLimit(int milliseconds)
SetProcessSuppressionEnabled(bool flag)
#if PLATFORM(COCOA)
SetQOS(int latencyQOS, int throughputQOS)