<!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>[192595] trunk/Source/WebCore</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/192595">192595</a></dd>
<dt>Author</dt> <dd>akling@apple.com</dd>
<dt>Date</dt> <dd>2015-11-18 15:48:48 -0800 (Wed, 18 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>ResourceUsageOverlay should have better accounting for reclaimable memory.
&lt;https://webkit.org/b/151407&gt;

Reviewed by Anders Carlsson.

Add code to inspect the purgeable state of VM regions when traversing the
web process VM map, and track reclaimable regions of memory separately.

Memory categories that have some amount of reclaimable memory are now
displayed with the reclaimable amount in brackets, e.g &quot;123.45 MB [56.78MB]&quot;

* page/ResourceUsageOverlay.h:
* page/cocoa/ResourceUsageOverlayCocoa.mm:
(WebCore::ResourceUsageOverlay::platformDraw):
(WebCore::TagInfo::TagInfo):
(WebCore::pagesPerVMTag):
(WebCore::runSamplerThread):
(WebCore::dirtyPagesPerVMTag): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorepageResourceUsageOverlayh">trunk/Source/WebCore/page/ResourceUsageOverlay.h</a></li>
<li><a href="#trunkSourceWebCorepagecocoaResourceUsageOverlayCocoamm">trunk/Source/WebCore/page/cocoa/ResourceUsageOverlayCocoa.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (192594 => 192595)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-11-18 23:47:52 UTC (rev 192594)
+++ trunk/Source/WebCore/ChangeLog        2015-11-18 23:48:48 UTC (rev 192595)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2015-11-18  Andreas Kling  &lt;akling@apple.com&gt;
+
+        ResourceUsageOverlay should have better accounting for reclaimable memory.
+        &lt;https://webkit.org/b/151407&gt;
+
+        Reviewed by Anders Carlsson.
+
+        Add code to inspect the purgeable state of VM regions when traversing the
+        web process VM map, and track reclaimable regions of memory separately.
+
+        Memory categories that have some amount of reclaimable memory are now
+        displayed with the reclaimable amount in brackets, e.g &quot;123.45 MB [56.78MB]&quot;
+
+        * page/ResourceUsageOverlay.h:
+        * page/cocoa/ResourceUsageOverlayCocoa.mm:
+        (WebCore::ResourceUsageOverlay::platformDraw):
+        (WebCore::TagInfo::TagInfo):
+        (WebCore::pagesPerVMTag):
+        (WebCore::runSamplerThread):
+        (WebCore::dirtyPagesPerVMTag): Deleted.
+
</ins><span class="cx"> 2015-11-18  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Client Blocked Resource Requests causes Crash under InspectorPageAgent::cachedResource
</span></span></pre></div>
<a id="trunkSourceWebCorepageResourceUsageOverlayh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/ResourceUsageOverlay.h (192594 => 192595)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/ResourceUsageOverlay.h        2015-11-18 23:47:52 UTC (rev 192594)
+++ trunk/Source/WebCore/page/ResourceUsageOverlay.h        2015-11-18 23:48:48 UTC (rev 192595)
</span><span class="lines">@@ -81,7 +81,7 @@
</span><span class="cx">     RetainPtr&lt;CALayer&gt; m_layer;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    static const int normalWidth = 550;
</del><ins>+    static const int normalWidth = 570;
</ins><span class="cx">     static const int normalHeight = 130;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepagecocoaResourceUsageOverlayCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/cocoa/ResourceUsageOverlayCocoa.mm (192594 => 192595)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/cocoa/ResourceUsageOverlayCocoa.mm        2015-11-18 23:47:52 UTC (rev 192594)
+++ trunk/Source/WebCore/page/cocoa/ResourceUsageOverlayCocoa.mm        2015-11-18 23:48:48 UTC (rev 192595)
</span><span class="lines">@@ -146,6 +146,7 @@
</span><span class="cx">     String name;
</span><span class="cx">     RetainPtr&lt;CGColorRef&gt; color;
</span><span class="cx">     RingBuffer&lt;size_t&gt; history;
</span><ins>+    RingBuffer&lt;size_t&gt; reclaimableHistory;
</ins><span class="cx">     bool isSubcategory { false };
</span><span class="cx">     unsigned type { MemoryCategory::NumberOfCategories };
</span><span class="cx"> };
</span><span class="lines">@@ -411,8 +412,13 @@
</span><span class="cx"> 
</span><span class="cx">     float y = 50;
</span><span class="cx">     for (auto&amp; category : data.categories) {
</span><ins>+        String label = String::format(&quot;% 11s: %s&quot;, category.name.ascii().data(), formatByteNumber(category.history.last()).ascii().data());
+        size_t reclaimable = category.reclaimableHistory.last();
+        if (reclaimable)
+            label = label + String::format(&quot; [%s]&quot;, formatByteNumber(reclaimable).ascii().data());
+
</ins><span class="cx">         // FIXME: Show size/capacity of GC heap.
</span><del>-        showText(context, 10, y, category.color.get(), String::format(&quot;% 11s: %s&quot;, category.name.ascii().data(), formatByteNumber(category.history.last()).ascii().data()));
</del><ins>+        showText(context, 10, y, category.color.get(), label);
</ins><span class="cx">         y += 10;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -424,22 +430,49 @@
</span><span class="cx">     drawMemoryPie(context, pieRect, data);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static std::array&lt;size_t, 256&gt; dirtyPagesPerVMTag()
</del><ins>+struct TagInfo {
+    TagInfo() { }
+    size_t dirty { 0 };
+    size_t reclaimable { 0 };
+};
+
+static std::array&lt;TagInfo, 256&gt; pagesPerVMTag()
</ins><span class="cx"> {
</span><del>-    std::array&lt;size_t, 256&gt; dirty;
-    dirty.fill(0);
</del><ins>+    std::array&lt;TagInfo, 256&gt; tags;
</ins><span class="cx">     task_t task = mach_task_self();
</span><span class="cx">     mach_vm_size_t size;
</span><span class="cx">     uint32_t depth = 0;
</span><span class="cx">     struct vm_region_submap_info_64 info = { };
</span><span class="cx">     mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
</span><span class="cx">     for (mach_vm_address_t addr = 0; ; addr += size) {
</span><ins>+        int purgeableState;
+        if (mach_vm_purgable_control(task, addr, VM_PURGABLE_GET_STATE, &amp;purgeableState) != KERN_SUCCESS)
+            purgeableState = VM_PURGABLE_DENY;
+
</ins><span class="cx">         kern_return_t kr = mach_vm_region_recurse(task, &amp;addr, &amp;size, &amp;depth, (vm_region_info_t)&amp;info, &amp;count);
</span><span class="cx">         if (kr != KERN_SUCCESS)
</span><span class="cx">             break;
</span><del>-        dirty[info.user_tag] += info.pages_dirtied;
</del><ins>+
+        if (purgeableState == VM_PURGABLE_VOLATILE) {
+            tags[info.user_tag].reclaimable += info.pages_resident;
+            continue;
+        }
+
+        if (purgeableState == VM_PURGABLE_EMPTY) {
+            static size_t vmPageSize = getpagesize();
+            tags[info.user_tag].reclaimable += size / vmPageSize;
+            continue;
+        }
+
+        bool anonymous = !info.external_pager;
+        if (anonymous) {
+            tags[info.user_tag].dirty += info.pages_resident - info.pages_reusable;
+            tags[info.user_tag].reclaimable += info.pages_reusable;
+        } else
+            tags[info.user_tag].dirty += info.pages_dirtied;
</ins><span class="cx">     }
</span><del>-    return dirty;
</del><ins>+
+    return tags;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static float cpuUsage()
</span><span class="lines">@@ -504,26 +537,27 @@
</span><span class="cx">     auto&amp; data = sharedData();
</span><span class="cx">     while (1) {
</span><span class="cx">         float cpu = cpuUsage();
</span><del>-        auto dirtyPages = dirtyPagesPerVMTag();
</del><ins>+        auto tags = pagesPerVMTag();
</ins><span class="cx">         Vector&lt;CALayer *, 8&gt; layers;
</span><span class="cx"> 
</span><span class="cx">         {
</span><span class="cx">             LockHolder locker(data.lock);
</span><span class="cx">             data.cpuHistory.append(cpu);
</span><span class="cx"> 
</span><del>-            std::array&lt;size_t, MemoryCategory::NumberOfCategories&gt; dirtyPagesPerCategory;
-            dirtyPagesPerCategory.fill(0);
</del><ins>+            std::array&lt;TagInfo, MemoryCategory::NumberOfCategories&gt; pagesPerCategory;
</ins><span class="cx"> 
</span><span class="cx">             size_t totalDirtyPages = 0;
</span><span class="cx">             for (unsigned i = 0; i &lt; 256; ++i) {
</span><del>-                dirtyPagesPerCategory[categoryForVMTag(i)] += dirtyPages[i];
-                totalDirtyPages += dirtyPages[i];
</del><ins>+                pagesPerCategory[categoryForVMTag(i)].dirty += tags[i].dirty;
+                pagesPerCategory[categoryForVMTag(i)].reclaimable += tags[i].reclaimable;
+                totalDirtyPages += tags[i].dirty;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             for (auto&amp; category : data.categories) {
</span><span class="cx">                 if (category.isSubcategory) // Only do automatic tallying for top-level categories.
</span><span class="cx">                     continue;
</span><del>-                category.history.append(dirtyPagesPerCategory[category.type] * vmPageSize);
</del><ins>+                category.history.append(pagesPerCategory[category.type].dirty * vmPageSize);
+                category.reclaimableHistory.append(pagesPerCategory[category.type].reclaimable * vmPageSize);
</ins><span class="cx">             }
</span><span class="cx">             data.totalDirty.append(totalDirtyPages * vmPageSize);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>