<!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>[215055] trunk/Source/WTF</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/215055">215055</a></dd>
<dt>Author</dt> <dd>akling@apple.com</dd>
<dt>Date</dt> <dd>2017-04-06 13:18:52 -0700 (Thu, 06 Apr 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Kill any WebContent process using over 16 GB of memory.
https://bugs.webkit.org/show_bug.cgi?id=170515
&lt;rdar://problem/29930931&gt;

Reviewed by Antti Koivisto.

Restructure the code since it was getting out of sync with the intended behavior.
Now there's a thresholdForMemoryKill() which returns the current memory limit based
on the process status.

The memory usage policy is separated from the killing, and now only drives the
asynchronous invocations of pressure relief that occur when we pass over one of
the policy edges (now 1GB for Conservative, 2GB for Strict.)

Removed the &quot;Panic&quot; policy and moved the memory kill logic to shrinkOrDie().

Behavior as of this patch:

    - Everyone gets killed over 16 GB.
    - Inactive processes get killed over 4 GB.
    - Strict memory usage policy kicks in at 2 GB.
    - Conservative memory usage policy at 1 GB.

Like before, we make a best-effort attempt to free up memory before killing the process.

* wtf/MemoryPressureHandler.cpp:
(WTF::toString):
(WTF::MemoryPressureHandler::thresholdForMemoryKill):
(WTF::thresholdForPolicy):
(WTF::policyForFootprint):
(WTF::MemoryPressureHandler::shrinkOrDie):
(WTF::MemoryPressureHandler::setMemoryUsagePolicyBasedOnFootprint):
(WTF::MemoryPressureHandler::measurementTimerFired):
* wtf/MemoryPressureHandler.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfMemoryPressureHandlercpp">trunk/Source/WTF/wtf/MemoryPressureHandler.cpp</a></li>
<li><a href="#trunkSourceWTFwtfMemoryPressureHandlerh">trunk/Source/WTF/wtf/MemoryPressureHandler.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (215054 => 215055)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2017-04-06 20:03:55 UTC (rev 215054)
+++ trunk/Source/WTF/ChangeLog        2017-04-06 20:18:52 UTC (rev 215055)
</span><span class="lines">@@ -1,3 +1,40 @@
</span><ins>+2017-04-06  Andreas Kling  &lt;akling@apple.com&gt;
+
+        Kill any WebContent process using over 16 GB of memory.
+        https://bugs.webkit.org/show_bug.cgi?id=170515
+        &lt;rdar://problem/29930931&gt;
+
+        Reviewed by Antti Koivisto.
+
+        Restructure the code since it was getting out of sync with the intended behavior.
+        Now there's a thresholdForMemoryKill() which returns the current memory limit based
+        on the process status.
+
+        The memory usage policy is separated from the killing, and now only drives the
+        asynchronous invocations of pressure relief that occur when we pass over one of
+        the policy edges (now 1GB for Conservative, 2GB for Strict.)
+
+        Removed the &quot;Panic&quot; policy and moved the memory kill logic to shrinkOrDie().
+
+        Behavior as of this patch:
+
+            - Everyone gets killed over 16 GB.
+            - Inactive processes get killed over 4 GB.
+            - Strict memory usage policy kicks in at 2 GB.
+            - Conservative memory usage policy at 1 GB.
+
+        Like before, we make a best-effort attempt to free up memory before killing the process.
+
+        * wtf/MemoryPressureHandler.cpp:
+        (WTF::toString):
+        (WTF::MemoryPressureHandler::thresholdForMemoryKill):
+        (WTF::thresholdForPolicy):
+        (WTF::policyForFootprint):
+        (WTF::MemoryPressureHandler::shrinkOrDie):
+        (WTF::MemoryPressureHandler::setMemoryUsagePolicyBasedOnFootprint):
+        (WTF::MemoryPressureHandler::measurementTimerFired):
+        * wtf/MemoryPressureHandler.h:
+
</ins><span class="cx"> 2017-04-05  Andreas Kling  &lt;akling@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Make inactive web processes behave as though under memory pressure.
</span></span></pre></div>
<a id="trunkSourceWTFwtfMemoryPressureHandlercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/MemoryPressureHandler.cpp (215054 => 215055)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/MemoryPressureHandler.cpp        2017-04-06 20:03:55 UTC (rev 215054)
+++ trunk/Source/WTF/wtf/MemoryPressureHandler.cpp        2017-04-06 20:18:52 UTC (rev 215055)
</span><span class="lines">@@ -71,11 +71,21 @@
</span><span class="cx">     case MemoryUsagePolicy::Unrestricted: return &quot;Unrestricted&quot;;
</span><span class="cx">     case MemoryUsagePolicy::Conservative: return &quot;Conservative&quot;;
</span><span class="cx">     case MemoryUsagePolicy::Strict: return &quot;Strict&quot;;
</span><del>-    case MemoryUsagePolicy::Panic: return &quot;Panic&quot;;
</del><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+size_t MemoryPressureHandler::thresholdForMemoryKill()
+{
+#if CPU(X86_64) || CPU(ARM64)
+    if (m_processState == WebsamProcessState::Active)
+        return 16 * GB;
+    return 4 * GB;
+#else
+    return 3 * GB;
+#endif
+}
+
</ins><span class="cx"> static size_t thresholdForPolicy(MemoryUsagePolicy policy)
</span><span class="cx"> {
</span><span class="cx">     switch (policy) {
</span><span class="lines">@@ -83,12 +93,6 @@
</span><span class="cx">         return 1 * GB;
</span><span class="cx">     case MemoryUsagePolicy::Strict:
</span><span class="cx">         return 2 * GB;
</span><del>-    case MemoryUsagePolicy::Panic:
-#if CPU(X86_64) || CPU(ARM64)
-        return 4 * GB;
-#else
-        return 3 * GB;
-#endif
</del><span class="cx">     case MemoryUsagePolicy::Unrestricted:
</span><span class="cx">     default:
</span><span class="cx">         ASSERT_NOT_REACHED();
</span><span class="lines">@@ -98,8 +102,6 @@
</span><span class="cx"> 
</span><span class="cx"> static MemoryUsagePolicy policyForFootprint(size_t footprint)
</span><span class="cx"> {
</span><del>-    if (footprint &gt;= thresholdForPolicy(MemoryUsagePolicy::Panic))
-        return MemoryUsagePolicy::Panic;
</del><span class="cx">     if (footprint &gt;= thresholdForPolicy(MemoryUsagePolicy::Strict))
</span><span class="cx">         return MemoryUsagePolicy::Strict;
</span><span class="cx">     if (footprint &gt;= thresholdForPolicy(MemoryUsagePolicy::Conservative))
</span><span class="lines">@@ -107,63 +109,60 @@
</span><span class="cx">     return MemoryUsagePolicy::Unrestricted;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MemoryPressureHandler::measurementTimerFired()
</del><ins>+void MemoryPressureHandler::shrinkOrDie()
</ins><span class="cx"> {
</span><ins>+    RELEASE_LOG(MemoryPressure, &quot;Process is above the memory kill threshold. Trying to shrink down.&quot;);
+    releaseMemory(Critical::Yes, Synchronous::Yes);
+
</ins><span class="cx">     auto footprint = memoryFootprint();
</span><del>-    if (!footprint)
</del><ins>+    RELEASE_ASSERT(footprint);
+    RELEASE_LOG(MemoryPressure, &quot;New memory footprint: %lu MB&quot;, footprint.value() / MB);
+
+    if (footprint.value() &lt; thresholdForMemoryKill()) {
+        RELEASE_LOG(MemoryPressure, &quot;Shrank below memory kill threshold. Process gets to live.&quot;);
+        setMemoryUsagePolicyBasedOnFootprint(footprint.value());
</ins><span class="cx">         return;
</span><ins>+    }
</ins><span class="cx"> 
</span><del>-    RELEASE_LOG(MemoryPressure, &quot;Current memory footprint: %lu MB&quot;, footprint.value() / MB);
</del><ins>+    RELEASE_ASSERT(m_memoryKillCallback);
+    m_memoryKillCallback();
+}
</ins><span class="cx"> 
</span><del>-    auto newPolicy = policyForFootprint(footprint.value());
-    if (newPolicy == m_memoryUsagePolicy) {
-        if (m_memoryUsagePolicy != MemoryUsagePolicy::Panic)
-            return;
-        RELEASE_LOG(MemoryPressure, &quot;Memory usage still above panic threshold&quot;);
-    } else
-        RELEASE_LOG(MemoryPressure, &quot;Memory usage policy changed: %s -&gt; %s&quot;, toString(m_memoryUsagePolicy), toString(newPolicy));
</del><ins>+void MemoryPressureHandler::setMemoryUsagePolicyBasedOnFootprint(size_t footprint)
+{
+    auto newPolicy = policyForFootprint(footprint);
+    if (newPolicy == m_memoryUsagePolicy)
+        return;
</ins><span class="cx"> 
</span><ins>+    RELEASE_LOG(MemoryPressure, &quot;Memory usage policy changed: %s -&gt; %s&quot;, toString(m_memoryUsagePolicy), toString(newPolicy));
</ins><span class="cx">     m_memoryUsagePolicy = newPolicy;
</span><span class="cx">     memoryPressureStatusChanged();
</span><ins>+}
</ins><span class="cx"> 
</span><del>-    if (newPolicy == MemoryUsagePolicy::Unrestricted)
</del><ins>+void MemoryPressureHandler::measurementTimerFired()
+{
+    auto footprint = memoryFootprint();
+    if (!footprint)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    if (newPolicy == MemoryUsagePolicy::Conservative) {
-        // FIXME: Implement this policy by choosing which caches should respect it, and hooking them up.
</del><ins>+    RELEASE_LOG(MemoryPressure, &quot;Current memory footprint: %lu MB&quot;, footprint.value() / MB);
+    if (footprint.value() &gt;= thresholdForMemoryKill()) {
+        shrinkOrDie();
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (newPolicy == MemoryUsagePolicy::Strict) {
-        RELEASE_LOG(MemoryPressure, &quot;Attempting to reduce memory footprint by freeing less important objects.&quot;);
</del><ins>+    setMemoryUsagePolicyBasedOnFootprint(footprint.value());
+
+    switch (m_memoryUsagePolicy) {
+    case MemoryUsagePolicy::Unrestricted:
+        break;
+    case MemoryUsagePolicy::Conservative:
</ins><span class="cx">         releaseMemory(Critical::No, Synchronous::No);
</span><del>-        return;
-    }
-
-    RELEASE_ASSERT(newPolicy == MemoryUsagePolicy::Panic);
-
-    RELEASE_LOG(MemoryPressure, &quot;Attempting to reduce memory footprint by freeing more important objects.&quot;);
-    if (m_processState == WebsamProcessState::Active) {
</del><ins>+        break;
+    case MemoryUsagePolicy::Strict:
</ins><span class="cx">         releaseMemory(Critical::Yes, Synchronous::No);
</span><del>-        return;
</del><ins>+        break;
</ins><span class="cx">     }
</span><del>-
-    releaseMemory(Critical::Yes, Synchronous::Yes);
-
-    // Remeasure footprint to see how well the pressure handler did.
-    footprint = memoryFootprint();
-    RELEASE_ASSERT(footprint);
-
-    RELEASE_LOG(MemoryPressure, &quot;New memory footprint: %lu MB&quot;, footprint.value() / MB);
-    if (footprint.value() &lt; thresholdForPolicy(MemoryUsagePolicy::Panic)) {
-        m_memoryUsagePolicy = policyForFootprint(footprint.value());
-        RELEASE_LOG(MemoryPressure, &quot;Pressure reduced below panic threshold. New memory usage policy: %s&quot;, toString(m_memoryUsagePolicy));
-        memoryPressureStatusChanged();
-        return;
-    }
-
-    if (m_memoryKillCallback)
-        m_memoryKillCallback();
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MemoryPressureHandler::setProcessState(WebsamProcessState state)
</span></span></pre></div>
<a id="trunkSourceWTFwtfMemoryPressureHandlerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/MemoryPressureHandler.h (215054 => 215055)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/MemoryPressureHandler.h        2017-04-06 20:03:55 UTC (rev 215054)
+++ trunk/Source/WTF/wtf/MemoryPressureHandler.h        2017-04-06 20:18:52 UTC (rev 215055)
</span><span class="lines">@@ -49,7 +49,6 @@
</span><span class="cx">     Unrestricted, // Allocate as much as you want
</span><span class="cx">     Conservative, // Maybe you don't cache every single thing
</span><span class="cx">     Strict, // Time to start pinching pennies for real
</span><del>-    Panic, // OH GOD WE'RE SINKING, THROW EVERYTHING OVERBOARD
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> enum class WebsamProcessState {
</span><span class="lines">@@ -141,6 +140,7 @@
</span><span class="cx">     WebsamProcessState processState() const { return m_processState; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    size_t thresholdForMemoryKill();
</ins><span class="cx">     void memoryPressureStatusChanged();
</span><span class="cx"> 
</span><span class="cx">     void uninstall();
</span><span class="lines">@@ -154,8 +154,9 @@
</span><span class="cx">     void platformReleaseMemory(Critical);
</span><span class="cx">     void platformInitialize();
</span><span class="cx"> 
</span><del>-    NO_RETURN_DUE_TO_CRASH void didExceedMemoryLimitAndFailedToRecover();
</del><span class="cx">     void measurementTimerFired();
</span><ins>+    void shrinkOrDie();
+    void setMemoryUsagePolicyBasedOnFootprint(size_t);
</ins><span class="cx"> 
</span><span class="cx"> #if OS(LINUX)
</span><span class="cx">     class EventFDPoller {
</span></span></pre>
</div>
</div>

</body>
</html>