Title: [214294] trunk/Source
Revision
214294
Author
[email protected]
Date
2017-03-22 21:14:03 -0700 (Wed, 22 Mar 2017)

Log Message

Let MemoryPressureHandler track whether the process is active or inactive.
<https://webkit.org/b/169990>

Reviewed by Antti Koivisto.

Source/WebCore:

Have PerformanceMonitor inform MemoryPressureHandler about relevant
changes to the page activity states.

Also change the "1 hour after last page load" policy to "1 hour after
last being visible in an active window."

* page/MainFrame.cpp:
(WebCore::MainFrame::didCompleteLoad):
* page/MainFrame.h:
* page/MemoryRelease.cpp:
(WebCore::processIsEligibleForMemoryKill): Deleted.
* page/MemoryRelease.h:
* page/Page.h:
(WebCore::Page::performanceMonitor):
* page/PerformanceMonitor.cpp:
(WebCore::PerformanceMonitor::PerformanceMonitor):
(WebCore::PerformanceMonitor::activityStateChanged):
(WebCore::PerformanceMonitor::processMayBecomeInactiveTimerFired):
(WebCore::PerformanceMonitor::updateProcessStateForMemoryPressure):
* page/PerformanceMonitor.h:

Source/WebKit2:

* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::initializeWebProcess):

Source/WTF:

An active process is a process that meets any of these criteria:

    - Has had a visible Page in an active window in the last hour
    - Is playing audio

This replaces the old mechanism where MemoryPressureHandler would invoke
a callback to know whether the process was eligible for a memory kill.
Instead we now plumb the relevant information down from WebCore and kill
based on this activity state.

* wtf/MemoryPressureHandler.cpp:
(WTF::MemoryPressureHandler::measurementTimerFired):
(WTF::MemoryPressureHandler::setProcessState):
* wtf/MemoryPressureHandler.h:
(WTF::MemoryPressureHandler::setMemoryKillCallback):
(WTF::MemoryPressureHandler::processState):
(WTF::MemoryPressureHandler::setProcessIsEligibleForMemoryKillCallback): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (214293 => 214294)


--- trunk/Source/WTF/ChangeLog	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WTF/ChangeLog	2017-03-23 04:14:03 UTC (rev 214294)
@@ -1,3 +1,28 @@
+2017-03-22  Andreas Kling  <[email protected]>
+
+        Let MemoryPressureHandler track whether the process is active or inactive.
+        <https://webkit.org/b/169990>
+
+        Reviewed by Antti Koivisto.
+
+        An active process is a process that meets any of these criteria:
+
+            - Has had a visible Page in an active window in the last hour
+            - Is playing audio
+
+        This replaces the old mechanism where MemoryPressureHandler would invoke
+        a callback to know whether the process was eligible for a memory kill.
+        Instead we now plumb the relevant information down from WebCore and kill
+        based on this activity state.
+
+        * wtf/MemoryPressureHandler.cpp:
+        (WTF::MemoryPressureHandler::measurementTimerFired):
+        (WTF::MemoryPressureHandler::setProcessState):
+        * wtf/MemoryPressureHandler.h:
+        (WTF::MemoryPressureHandler::setMemoryKillCallback):
+        (WTF::MemoryPressureHandler::processState):
+        (WTF::MemoryPressureHandler::setProcessIsEligibleForMemoryKillCallback): Deleted.
+
 2017-03-20  Simon Fraser  <[email protected]>
 
         Add a system trace point for memory warning handling

Modified: trunk/Source/WTF/wtf/MemoryPressureHandler.cpp (214293 => 214294)


--- trunk/Source/WTF/wtf/MemoryPressureHandler.cpp	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WTF/wtf/MemoryPressureHandler.cpp	2017-03-23 04:14:03 UTC (rev 214294)
@@ -143,11 +143,9 @@
     RELEASE_ASSERT(newPolicy == MemoryUsagePolicy::Panic);
 
     RELEASE_LOG(MemoryPressure, "Attempting to reduce memory footprint by freeing more important objects.");
-    if (m_processIsEligibleForMemoryKillCallback) {
-        if (!m_processIsEligibleForMemoryKillCallback()) {
-            releaseMemory(Critical::Yes, Synchronous::No);
-            return;
-        }
+    if (m_processState == WebsamProcessState::Active) {
+        releaseMemory(Critical::Yes, Synchronous::No);
+        return;
     }
 
     releaseMemory(Critical::Yes, Synchronous::Yes);
@@ -168,6 +166,13 @@
         m_memoryKillCallback();
 }
 
+void MemoryPressureHandler::setProcessState(WebsamProcessState state)
+{
+    if (m_processState == state)
+        return;
+    m_processState = state;
+}
+
 void MemoryPressureHandler::beginSimulatedMemoryPressure()
 {
     if (m_isSimulatingMemoryPressure)

Modified: trunk/Source/WTF/wtf/MemoryPressureHandler.h (214293 => 214294)


--- trunk/Source/WTF/wtf/MemoryPressureHandler.h	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WTF/wtf/MemoryPressureHandler.h	2017-03-23 04:14:03 UTC (rev 214294)
@@ -52,6 +52,11 @@
     Panic, // OH GOD WE'RE SINKING, THROW EVERYTHING OVERBOARD
 };
 
+enum class WebsamProcessState {
+    Active,
+    Inactive,
+};
+
 enum class Critical { No, Yes };
 enum class Synchronous { No, Yes };
 
@@ -67,7 +72,6 @@
     WTF_EXPORT_PRIVATE void setShouldUsePeriodicMemoryMonitor(bool);
 
     void setMemoryKillCallback(WTF::Function<void()> function) { m_memoryKillCallback = WTFMove(function); }
-    void setProcessIsEligibleForMemoryKillCallback(WTF::Function<bool()> function) { m_processIsEligibleForMemoryKillCallback = WTFMove(function); }
     void setMemoryPressureStatusChangedCallback(WTF::Function<void(bool)> function) { m_memoryPressureStatusChangedCallback = WTFMove(function); }
 
     void setLowMemoryHandler(LowMemoryHandler&& handler)
@@ -140,6 +144,9 @@
     WTF_EXPORT_PRIVATE void beginSimulatedMemoryPressure();
     WTF_EXPORT_PRIVATE void endSimulatedMemoryPressure();
 
+    WTF_EXPORT_PRIVATE void setProcessState(WebsamProcessState);
+    WebsamProcessState processState() const { return m_processState; }
+
 private:
     void memoryPressureStatusChanged();
 
@@ -177,6 +184,8 @@
     };
 #endif
 
+    WebsamProcessState m_processState { WebsamProcessState::Inactive };
+
     bool m_installed { false };
     LowMemoryHandler m_lowMemoryHandler;
 
@@ -186,7 +195,6 @@
     std::unique_ptr<RunLoop::Timer<MemoryPressureHandler>> m_measurementTimer;
     MemoryUsagePolicy m_memoryUsagePolicy { MemoryUsagePolicy::Unrestricted };
     WTF::Function<void()> m_memoryKillCallback;
-    WTF::Function<bool()> m_processIsEligibleForMemoryKillCallback;
     WTF::Function<void(bool)> m_memoryPressureStatusChangedCallback;
 
 #if OS(WINDOWS)
@@ -213,3 +221,4 @@
 using WTF::Critical;
 using WTF::MemoryPressureHandler;
 using WTF::Synchronous;
+using WTF::WebsamProcessState;

Modified: trunk/Source/WebCore/ChangeLog (214293 => 214294)


--- trunk/Source/WebCore/ChangeLog	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WebCore/ChangeLog	2017-03-23 04:14:03 UTC (rev 214294)
@@ -1,3 +1,31 @@
+2017-03-22  Andreas Kling  <[email protected]>
+
+        Let MemoryPressureHandler track whether the process is active or inactive.
+        <https://webkit.org/b/169990>
+
+        Reviewed by Antti Koivisto.
+
+        Have PerformanceMonitor inform MemoryPressureHandler about relevant
+        changes to the page activity states.
+
+        Also change the "1 hour after last page load" policy to "1 hour after
+        last being visible in an active window."
+
+        * page/MainFrame.cpp:
+        (WebCore::MainFrame::didCompleteLoad):
+        * page/MainFrame.h:
+        * page/MemoryRelease.cpp:
+        (WebCore::processIsEligibleForMemoryKill): Deleted.
+        * page/MemoryRelease.h:
+        * page/Page.h:
+        (WebCore::Page::performanceMonitor):
+        * page/PerformanceMonitor.cpp:
+        (WebCore::PerformanceMonitor::PerformanceMonitor):
+        (WebCore::PerformanceMonitor::activityStateChanged):
+        (WebCore::PerformanceMonitor::processMayBecomeInactiveTimerFired):
+        (WebCore::PerformanceMonitor::updateProcessStateForMemoryPressure):
+        * page/PerformanceMonitor.h:
+
 2017-03-22  Youenn Fablet  <[email protected]>
 
         Support RTCPeerConnectionState

Modified: trunk/Source/WebCore/page/MainFrame.cpp (214293 => 214294)


--- trunk/Source/WebCore/page/MainFrame.cpp	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WebCore/page/MainFrame.cpp	2017-03-23 04:14:03 UTC (rev 214294)
@@ -97,7 +97,6 @@
 
 void MainFrame::didCompleteLoad()
 {
-    m_timeOfLastCompletedLoad = MonotonicTime::now();
     performanceLogging().didReachPointOfInterest(PerformanceLogging::MainFrameLoadCompleted);
 }
 

Modified: trunk/Source/WebCore/page/MainFrame.h (214293 => 214294)


--- trunk/Source/WebCore/page/MainFrame.h	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WebCore/page/MainFrame.h	2017-03-23 04:14:03 UTC (rev 214294)
@@ -70,7 +70,6 @@
     PerformanceLogging& performanceLogging() const { return *m_performanceLogging; }
 
     void didCompleteLoad();
-    MonotonicTime timeOfLastCompletedLoad() const { return m_timeOfLastCompletedLoad; }
 
 private:
     MainFrame(Page&, PageConfiguration&);
@@ -94,8 +93,6 @@
 #endif
 
     std::unique_ptr<PerformanceLogging> m_performanceLogging;
-
-    MonotonicTime m_timeOfLastCompletedLoad;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/MemoryRelease.cpp (214293 => 214294)


--- trunk/Source/WebCore/page/MemoryRelease.cpp	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WebCore/page/MemoryRelease.cpp	2017-03-23 04:14:03 UTC (rev 214294)
@@ -193,33 +193,6 @@
     CRASH();
 }
 
-bool processIsEligibleForMemoryKill()
-{
-    bool hasVisiblePages = false;
-    bool hasAudiblePages = false;
-    bool hasMainFrameNavigatedInTheLastHour = false;
-
-    auto now = MonotonicTime::now();
-    Page::forEachPage([&] (Page& page) {
-        if (page.isUtilityPage())
-            return;
-        if (page.isVisible())
-            hasVisiblePages = true;
-        if (page.activityState() & ActivityState::IsAudible)
-            hasAudiblePages = true;
-        if (auto timeOfLastCompletedLoad = page.mainFrame().timeOfLastCompletedLoad()) {
-            if (now - timeOfLastCompletedLoad <= Seconds::fromMinutes(60))
-                hasMainFrameNavigatedInTheLastHour = true;
-        }
-    });
-
-    bool eligible = !hasVisiblePages && !hasAudiblePages && !hasMainFrameNavigatedInTheLastHour;
-    if (!eligible)
-        RELEASE_LOG(MemoryPressure, "Process not eligible for panic memory kill. Reasons: hasVisiblePages=%u, hasAudiblePages=%u, hasMainFrameNavigatedInTheLastHour=%u", hasVisiblePages, hasAudiblePages, hasMainFrameNavigatedInTheLastHour);
-
-    return eligible;
-}
-
 #if !PLATFORM(COCOA)
 void platformReleaseMemory(Critical) { }
 void jettisonExpensiveObjectsOnTopLevelNavigation() { }

Modified: trunk/Source/WebCore/page/MemoryRelease.h (214293 => 214294)


--- trunk/Source/WebCore/page/MemoryRelease.h	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WebCore/page/MemoryRelease.h	2017-03-23 04:14:03 UTC (rev 214294)
@@ -35,6 +35,5 @@
 WEBCORE_EXPORT void registerMemoryReleaseNotifyCallbacks();
 WEBCORE_EXPORT void logMemoryStatisticsAtTimeOfDeath();
 WEBCORE_EXPORT NO_RETURN_DUE_TO_CRASH void didExceedMemoryLimitAndFailedToRecover();
-WEBCORE_EXPORT bool processIsEligibleForMemoryKill();
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/Page.h (214293 => 214294)


--- trunk/Source/WebCore/page/Page.h	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WebCore/page/Page.h	2017-03-23 04:14:03 UTC (rev 214294)
@@ -226,6 +226,7 @@
 #endif
     LibWebRTCProvider& libWebRTCProvider() { return m_libWebRTCProvider.get(); }
     RTCController& rtcController() { return m_rtcController; }
+    PerformanceMonitor* performanceMonitor() { return m_performanceMonitor.get(); }
 
     ValidationMessageClient* validationMessageClient() const { return m_validationMessageClient.get(); }
     void updateValidationBubbleStateIfNeeded();

Modified: trunk/Source/WebCore/page/PerformanceMonitor.cpp (214293 => 214294)


--- trunk/Source/WebCore/page/PerformanceMonitor.cpp	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WebCore/page/PerformanceMonitor.cpp	2017-03-23 04:14:03 UTC (rev 214294)
@@ -48,6 +48,8 @@
 
 static const std::chrono::seconds memoryUsageMeasurementDelay { 10 };
 
+static const std::chrono::minutes delayBeforeProcessMayBecomeInactive { 60 };
+
 static const double postPageLoadCPUUsageDomainReportingThreshold { 20.0 }; // Reporting pages using over 20% CPU is roughly equivalent to reporting the 10% worst pages.
 #if !PLATFORM(IOS)
 static const uint64_t postPageLoadMemoryUsageDomainReportingThreshold { 2048 * MB };
@@ -69,6 +71,7 @@
     , m_perActivityStateCPUUsageTimer(*this, &PerformanceMonitor::measurePerActivityStateCPUUsage)
     , m_postPageLoadMemoryUsageTimer(*this, &PerformanceMonitor::measurePostLoadMemoryUsage)
     , m_postBackgroundingMemoryUsageTimer(*this, &PerformanceMonitor::measurePostBackgroundingMemoryUsage)
+    , m_processMayBecomeInactiveTimer(*this, &PerformanceMonitor::processMayBecomeInactiveTimerFired)
 {
     ASSERT(!page.isUtilityPage());
 
@@ -127,6 +130,14 @@
         else if (m_page.isOnlyNonUtilityPage())
             m_postBackgroundingMemoryUsageTimer.startOneShot(memoryUsageMeasurementDelay);
     }
+
+    if (newState & ActivityState::IsVisible && newState & ActivityState::WindowIsActive) {
+        m_processMayBecomeInactive = false;
+        m_processMayBecomeInactiveTimer.stop();
+    } else if (!m_processMayBecomeInactive && !m_processMayBecomeInactiveTimer.isActive())
+        m_processMayBecomeInactiveTimer.startOneShot(delayBeforeProcessMayBecomeInactive);
+
+    updateProcessStateForMemoryPressure();
 }
 
 enum class ReportingReason { HighCPUUsage, HighMemoryUsage };
@@ -282,4 +293,28 @@
     m_perActivityStateCPUTime = WTFMove(cpuTime);
 }
 
+void PerformanceMonitor::processMayBecomeInactiveTimerFired()
+{
+    m_processMayBecomeInactive = true;
+    updateProcessStateForMemoryPressure();
+}
+
+void PerformanceMonitor::updateProcessStateForMemoryPressure()
+{
+    bool hasAudiblePages = false;
+    bool mayBecomeInactive = true;
+
+    Page::forEachPage([&] (Page& page) {
+        if (!page.performanceMonitor())
+            return;
+        if (!page.performanceMonitor()->m_processMayBecomeInactive)
+            mayBecomeInactive = false;
+        if (page.activityState() & ActivityState::IsAudible)
+            hasAudiblePages = true;
+    });
+
+    bool isActiveProcess = !mayBecomeInactive || hasAudiblePages;
+    MemoryPressureHandler::singleton().setProcessState(isActiveProcess ? WebsamProcessState::Active : WebsamProcessState::Inactive);
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/PerformanceMonitor.h (214293 => 214294)


--- trunk/Source/WebCore/page/PerformanceMonitor.h	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WebCore/page/PerformanceMonitor.h	2017-03-23 04:14:03 UTC (rev 214294)
@@ -47,9 +47,10 @@
     void measurePostBackgroundingCPUUsage();
     void measurePerActivityStateCPUUsage();
     void measureCPUUsageInActivityState(ActivityStateForCPUSampling);
-
     void measurePostLoadMemoryUsage();
     void measurePostBackgroundingMemoryUsage();
+    void processMayBecomeInactiveTimerFired();
+    static void updateProcessStateForMemoryPressure();
 
     Page& m_page;
 
@@ -62,6 +63,9 @@
 
     Timer m_postPageLoadMemoryUsageTimer;
     Timer m_postBackgroundingMemoryUsageTimer;
+
+    Timer m_processMayBecomeInactiveTimer;
+    bool m_processMayBecomeInactive { true };
 };
 
 }

Modified: trunk/Source/WebKit2/ChangeLog (214293 => 214294)


--- trunk/Source/WebKit2/ChangeLog	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WebKit2/ChangeLog	2017-03-23 04:14:03 UTC (rev 214294)
@@ -1,3 +1,13 @@
+2017-03-22  Andreas Kling  <[email protected]>
+
+        Let MemoryPressureHandler track whether the process is active or inactive.
+        <https://webkit.org/b/169990>
+
+        Reviewed by Antti Koivisto.
+
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::initializeWebProcess):
+
 2017-03-21  Wenson Hsieh  <[email protected]>
 
         Add support for showing the platform data interaction caret

Modified: trunk/Source/WebKit2/WebProcess/WebProcess.cpp (214293 => 214294)


--- trunk/Source/WebKit2/WebProcess/WebProcess.cpp	2017-03-23 02:44:57 UTC (rev 214293)
+++ trunk/Source/WebKit2/WebProcess/WebProcess.cpp	2017-03-23 04:14:03 UTC (rev 214294)
@@ -270,9 +270,6 @@
         memoryPressureHandler.setMemoryKillCallback([] () {
             WebCore::didExceedMemoryLimitAndFailedToRecover();
         });
-        memoryPressureHandler.setProcessIsEligibleForMemoryKillCallback([] () {
-            return WebCore::processIsEligibleForMemoryKill();
-        });
 #endif
         memoryPressureHandler.setMemoryPressureStatusChangedCallback([this](bool isUnderMemoryPressure) {
             if (parentProcessConnection())
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to