Terminate service workers that use too much CPU / power
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 6 May 2019 21:44:01 +0000 (21:44 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 6 May 2019 21:44:01 +0000 (21:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=197626
<rdar://problem/50374707>

Reviewed by Geoffrey Garen.

Terminate service worker processes that use over 50% CPU on average over the last 8 minutes,
similarly to what we do for background WebContent processes.

* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::didExceedCPULimit):
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::initializeProcess):
* WebProcess/cocoa/WebProcessCocoa.mm:
(WebKit::WebProcess::updateCPULimit):
(WebKit::WebProcess::updateCPUMonitorState):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244979 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/ChangeLog
Source/WebKit/UIProcess/WebProcessProxy.cpp
Source/WebKit/WebProcess/WebProcess.cpp
Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm

index db17075..59e7ac9 100644 (file)
@@ -1,3 +1,22 @@
+2019-05-06  Chris Dumez  <cdumez@apple.com>
+
+        Terminate service workers that use too much CPU / power
+        https://bugs.webkit.org/show_bug.cgi?id=197626
+        <rdar://problem/50374707>
+
+        Reviewed by Geoffrey Garen.
+
+        Terminate service worker processes that use over 50% CPU on average over the last 8 minutes,
+        similarly to what we do for background WebContent processes.
+
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::didExceedCPULimit):
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::initializeProcess):
+        * WebProcess/cocoa/WebProcessCocoa.mm:
+        (WebKit::WebProcess::updateCPULimit):
+        (WebKit::WebProcess::updateCPUMonitorState):
+
 2019-05-06  Daniel Bates  <dabates@apple.com>
 
         Google Docs & Yahoo! Japan: Can’t compose characters with Chinese or Japanese keyboard
index d4f37d7..41d3004 100644 (file)
@@ -1338,7 +1338,10 @@ void WebProcessProxy::didExceedCPULimit()
     if (hasVisiblePage)
         return;
 
-    RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didExceedCPULimit() Terminating background WebProcess with pid %d that has exceeded the background CPU limit", this, processIdentifier());
+    if (isServiceWorkerProcess())
+        RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didExceedCPULimit() Terminating Service Worker process with pid %d that has exceeded the background CPU limit", this, processIdentifier());
+    else
+        RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didExceedCPULimit() Terminating background WebProcess with pid %d that has exceeded the background CPU limit", this, processIdentifier());
     logDiagnosticMessageForResourceLimitTermination(DiagnosticLoggingKeys::exceededBackgroundCPULimitKey());
     requestTermination(ProcessTerminationReason::ExceededCPULimit);
 }
index 7159766..6fa34f0 100644 (file)
@@ -237,6 +237,7 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter
     MessagePortChannelProvider::setSharedProvider(WebMessagePortChannelProvider::singleton());
     
     platformInitializeProcess(parameters);
+    updateCPULimit();
 }
 
 void WebProcess::initializeConnection(IPC::Connection* connection)
index 73df75c..e6a7a56 100644 (file)
@@ -121,6 +121,7 @@ using namespace WebCore;
 
 #if PLATFORM(MAC)
 static const Seconds cpuMonitoringInterval { 8_min };
+static const double serviceWorkerCPULimit { 0.5 }; // 50% average CPU usage over 8 minutes.
 #endif
 
 void WebProcess::platformSetCacheModel(CacheModel)
@@ -577,16 +578,19 @@ void WebProcess::updateCPULimit()
 {
 #if PLATFORM(MAC)
     Optional<double> cpuLimit;
-
-    // Use the largest limit among all pages in this process.
-    for (auto& page : m_pageMap.values()) {
-        auto pageCPULimit = page->cpuLimit();
-        if (!pageCPULimit) {
-            cpuLimit = WTF::nullopt;
-            break;
+    if (m_processType == ProcessType::ServiceWorker)
+        cpuLimit = serviceWorkerCPULimit;
+    else {
+        // Use the largest limit among all pages in this process.
+        for (auto& page : m_pageMap.values()) {
+            auto pageCPULimit = page->cpuLimit();
+            if (!pageCPULimit) {
+                cpuLimit = WTF::nullopt;
+                break;
+            }
+            if (!cpuLimit || pageCPULimit > cpuLimit.value())
+                cpuLimit = pageCPULimit;
         }
-        if (!cpuLimit || pageCPULimit > cpuLimit.value())
-            cpuLimit = pageCPULimit;
     }
 
     if (m_cpuLimit == cpuLimit)
@@ -608,7 +612,10 @@ void WebProcess::updateCPUMonitorState(CPUMonitorUpdateReason reason)
 
     if (!m_cpuMonitor) {
         m_cpuMonitor = std::make_unique<CPUMonitor>(cpuMonitoringInterval, [this](double cpuUsage) {
-            RELEASE_LOG(PerformanceLogging, "%p - WebProcess exceeded CPU limit of %.1f%% (was using %.1f%%) hasVisiblePages? %d", this, m_cpuLimit.value() * 100, cpuUsage * 100, hasVisibleWebPage());
+            if (m_processType == ProcessType::ServiceWorker)
+                RELEASE_LOG_ERROR(PerformanceLogging, "%p - Service worker process exceeded CPU limit of %.1f%% (was using %.1f%%)", this, m_cpuLimit.value() * 100, cpuUsage * 100);
+            else
+                RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcess exceeded CPU limit of %.1f%% (was using %.1f%%) hasVisiblePages? %d", this, m_cpuLimit.value() * 100, cpuUsage * 100, hasVisibleWebPage());
             parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedCPULimit(), 0);
         });
     } else if (reason == CPUMonitorUpdateReason::VisibilityHasChanged) {