Memory warning logging appears to capture resident footprint, missing compress/swap.
authorkrollin@apple.com <krollin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 13 Dec 2016 00:28:18 +0000 (00:28 +0000)
committerkrollin@apple.com <krollin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 13 Dec 2016 00:28:18 +0000 (00:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=165533
<rdar://problem/29318410>

Reviewed by Andreas Kling.

Have platformMemoryUsage return both resident and resident + swapped
values. This is now returned as a struct in a std::optional to better
support cases where values cannot or are not returned. Report these
values in logMemoryUsageChange.

Remove most of the ReliefLogger instances and their messages. We no
longer free up fastMalloc memory after each memory-release operation,
so there are no memory regions returned to the OS. Instead, we now
free up fastMalloc memory regions at the end of all memory-releasing
operations in one fell swoop and report a grand total of memory
returned.

No new tests -- no changes to user accessible functionality.

* page/MemoryRelease.cpp:
(WebCore::releaseNoncriticalMemory):
(WebCore::releaseCriticalMemory):
(WebCore::releaseMemory):
* page/cocoa/MemoryReleaseCocoa.mm:
(WebCore::platformReleaseMemory):
* platform/MemoryPressureHandler.cpp:
(WebCore::MemoryPressureHandler::releaseMemory):
(WebCore::MemoryPressureHandler::ReliefLogger::logMemoryUsageChange):
(WebCore::MemoryPressureHandler::ReliefLogger::platformMemoryUsage):
* platform/MemoryPressureHandler.h:
(WebCore::MemoryPressureHandler::ReliefLogger::ReliefLogger):
(WebCore::MemoryPressureHandler::ReliefLogger::~ReliefLogger):
(WebCore::MemoryPressureHandler::ReliefLogger::loggingEnabled):
* platform/cocoa/MemoryPressureHandlerCocoa.mm:
(WebCore::MemoryPressureHandler::platformReleaseMemory):
(WebCore::MemoryPressureHandler::ReliefLogger::platformMemoryUsage):
* platform/linux/MemoryPressureHandlerLinux.cpp:
* platform/win/MemoryPressureHandlerWin.cpp:
(WebCore::MemoryPressureHandler::ReliefLogger::platformMemoryUsage):

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

Source/WebCore/ChangeLog
Source/WebCore/page/MemoryRelease.cpp
Source/WebCore/page/cocoa/MemoryReleaseCocoa.mm
Source/WebCore/platform/MemoryPressureHandler.cpp
Source/WebCore/platform/MemoryPressureHandler.h
Source/WebCore/platform/cocoa/MemoryPressureHandlerCocoa.mm
Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp
Source/WebCore/platform/win/MemoryPressureHandlerWin.cpp

index aed3049..e60cf7f 100644 (file)
@@ -1,3 +1,46 @@
+2016-12-12  Keith Rollin  <krollin@apple.com>
+
+        Memory warning logging appears to capture resident footprint, missing compress/swap.
+        https://bugs.webkit.org/show_bug.cgi?id=165533
+        <rdar://problem/29318410>
+
+        Reviewed by Andreas Kling.
+
+        Have platformMemoryUsage return both resident and resident + swapped
+        values. This is now returned as a struct in a std::optional to better
+        support cases where values cannot or are not returned. Report these
+        values in logMemoryUsageChange.
+
+        Remove most of the ReliefLogger instances and their messages. We no
+        longer free up fastMalloc memory after each memory-release operation,
+        so there are no memory regions returned to the OS. Instead, we now
+        free up fastMalloc memory regions at the end of all memory-releasing
+        operations in one fell swoop and report a grand total of memory
+        returned.
+
+        No new tests -- no changes to user accessible functionality.
+
+        * page/MemoryRelease.cpp:
+        (WebCore::releaseNoncriticalMemory):
+        (WebCore::releaseCriticalMemory):
+        (WebCore::releaseMemory):
+        * page/cocoa/MemoryReleaseCocoa.mm:
+        (WebCore::platformReleaseMemory):
+        * platform/MemoryPressureHandler.cpp:
+        (WebCore::MemoryPressureHandler::releaseMemory):
+        (WebCore::MemoryPressureHandler::ReliefLogger::logMemoryUsageChange):
+        (WebCore::MemoryPressureHandler::ReliefLogger::platformMemoryUsage):
+        * platform/MemoryPressureHandler.h:
+        (WebCore::MemoryPressureHandler::ReliefLogger::ReliefLogger):
+        (WebCore::MemoryPressureHandler::ReliefLogger::~ReliefLogger):
+        (WebCore::MemoryPressureHandler::ReliefLogger::loggingEnabled):
+        * platform/cocoa/MemoryPressureHandlerCocoa.mm:
+        (WebCore::MemoryPressureHandler::platformReleaseMemory):
+        (WebCore::MemoryPressureHandler::ReliefLogger::platformMemoryUsage):
+        * platform/linux/MemoryPressureHandlerLinux.cpp:
+        * platform/win/MemoryPressureHandlerWin.cpp:
+        (WebCore::MemoryPressureHandler::ReliefLogger::platformMemoryUsage):
+
 2016-12-12  Chris Dumez  <cdumez@apple.com>
 
         Document.visibilityState should use an IDL string enumeration
index 4830fac..7affe29 100644 (file)
@@ -48,82 +48,45 @@ namespace WebCore {
 
 static void releaseNoncriticalMemory()
 {
-    {
-        MemoryPressureHandler::ReliefLogger log("Purge inactive FontData");
-        FontCache::singleton().purgeInactiveFontData();
-    }
+    FontCache::singleton().purgeInactiveFontData();
 
-    {
-        MemoryPressureHandler::ReliefLogger log("Clear WidthCaches");
-        clearWidthCaches();
-    }
+    clearWidthCaches();
 
-    {
-        MemoryPressureHandler::ReliefLogger log("Discard Selector Query Cache");
-        for (auto* document : Document::allDocuments())
-            document->clearSelectorQueryCache();
-    }
+    for (auto* document : Document::allDocuments())
+        document->clearSelectorQueryCache();
 
-    {
-        MemoryPressureHandler::ReliefLogger log("Prune MemoryCache dead resources");
-        MemoryCache::singleton().pruneDeadResourcesToSize(0);
-    }
+    MemoryCache::singleton().pruneDeadResourcesToSize(0);
 
-    {
-        MemoryPressureHandler::ReliefLogger log("Prune presentation attribute cache");
-        StyledElement::clearPresentationAttributeCache();
-    }
+    StyledElement::clearPresentationAttributeCache();
 
-    {
-        MemoryPressureHandler::ReliefLogger log("Clear inline stylesheet cache");
-        InlineStyleSheetOwner::clearCache();
-    }
+    InlineStyleSheetOwner::clearCache();
 }
 
 static void releaseCriticalMemory(Synchronous synchronous)
 {
-    {
-        MemoryPressureHandler::ReliefLogger log("Empty the PageCache");
-        // Right now, the only reason we call release critical memory while not under memory pressure is if the process is about to be suspended.
-        PruningReason pruningReason = MemoryPressureHandler::singleton().isUnderMemoryPressure() ? PruningReason::MemoryPressure : PruningReason::ProcessSuspended;
-        PageCache::singleton().pruneToSizeNow(0, pruningReason);
-    }
+    // Right now, the only reason we call release critical memory while not under memory pressure is if the process is about to be suspended.
+    PruningReason pruningReason = MemoryPressureHandler::singleton().isUnderMemoryPressure() ? PruningReason::MemoryPressure : PruningReason::ProcessSuspended;
+    PageCache::singleton().pruneToSizeNow(0, pruningReason);
 
-    {
-        MemoryPressureHandler::ReliefLogger log("Prune MemoryCache live resources");
-        MemoryCache::singleton().pruneLiveResourcesToSize(0, /*shouldDestroyDecodedDataForAllLiveResources*/ true);
-    }
+    MemoryCache::singleton().pruneLiveResourcesToSize(0, /*shouldDestroyDecodedDataForAllLiveResources*/ true);
 
-    {
-        MemoryPressureHandler::ReliefLogger log("Drain CSSValuePool");
-        CSSValuePool::singleton().drain();
-    }
+    CSSValuePool::singleton().drain();
 
-    {
-        MemoryPressureHandler::ReliefLogger log("Discard StyleResolvers");
-        Vector<RefPtr<Document>> documents;
-        copyToVector(Document::allDocuments(), documents);
-        for (auto& document : documents)
-            document->styleScope().clearResolver();
-    }
+    Vector<RefPtr<Document>> documents;
+    copyToVector(Document::allDocuments(), documents);
+    for (auto& document : documents)
+        document->styleScope().clearResolver();
 
-    {
-        MemoryPressureHandler::ReliefLogger log("Discard all JIT-compiled code");
-        GCController::singleton().deleteAllCode(JSC::DeleteAllCodeIfNotCollecting);
-    }
+    GCController::singleton().deleteAllCode(JSC::DeleteAllCodeIfNotCollecting);
 
 #if ENABLE(VIDEO)
-    {
-        MemoryPressureHandler::ReliefLogger log("Dropping buffered data from paused media elements");
-        for (auto* mediaElement : HTMLMediaElement::allMediaElements()) {
-            if (mediaElement->paused())
-                mediaElement->purgeBufferedDataIfPossible();
-        }
+    for (auto* mediaElement : HTMLMediaElement::allMediaElements()) {
+        if (mediaElement->paused())
+            mediaElement->purgeBufferedDataIfPossible();
     }
 #endif
 
     if (synchronous == Synchronous::Yes) {
-        MemoryPressureHandler::ReliefLogger log("Collecting JavaScript garbage");
         GCController::singleton().garbageCollectNow();
     } else {
 #if PLATFORM(IOS)
@@ -148,17 +111,14 @@ void releaseMemory(Critical critical, Synchronous synchronous)
 
     platformReleaseMemory(critical);
 
-    {
-        MemoryPressureHandler::ReliefLogger log("Release free FastMalloc memory");
-        // FastMalloc has lock-free thread specific caches that can only be cleared from the thread itself.
-        WorkerThread::releaseFastMallocFreeMemoryInAllThreads();
+    // FastMalloc has lock-free thread specific caches that can only be cleared from the thread itself.
+    WorkerThread::releaseFastMallocFreeMemoryInAllThreads();
 #if ENABLE(ASYNC_SCROLLING) && !PLATFORM(IOS)
-        ScrollingThread::dispatch([]() {
-            WTF::releaseFastMallocFreeMemory();
-        });
-#endif
+    ScrollingThread::dispatch([]() {
         WTF::releaseFastMallocFreeMemory();
-    }
+    });
+#endif
+    WTF::releaseFastMallocFreeMemory();
 
 #if ENABLE(RESOURCE_USAGE)
     Page::forEachPage([&](Page& page) {
index f8460a8..8d40f24 100644 (file)
@@ -37,21 +37,13 @@ namespace WebCore {
 
 void platformReleaseMemory(Critical)
 {
-    {
-        MemoryPressureHandler::ReliefLogger log("Purging SQLite caches");
-        _sqlite3_purgeEligiblePagerCacheMemory();
-    }
+    _sqlite3_purgeEligiblePagerCacheMemory();
+
+    for (auto& pool : LayerPool::allLayerPools())
+        pool->drain();
 
-    {
-        MemoryPressureHandler::ReliefLogger log("Drain LayerPools");
-        for (auto& pool : LayerPool::allLayerPools())
-            pool->drain();
-    }
 #if USE(IOSURFACE)
-    {
-        MemoryPressureHandler::ReliefLogger log("Drain IOSurfacePool");
-        IOSurfacePool::sharedPool().discardAllSurfaces();
-    }
+    IOSurfacePool::sharedPool().discardAllSurfaces();
 #endif
 }
 
index 95ac3f2..b9ac0e5 100644 (file)
@@ -61,6 +61,7 @@ void MemoryPressureHandler::releaseMemory(Critical critical, Synchronous synchro
     if (!m_lowMemoryHandler)
         return;
 
+    ReliefLogger log("Total");
     m_lowMemoryHandler(critical, synchronous);
     platformReleaseMemory(critical);
 }
@@ -75,19 +76,19 @@ void MemoryPressureHandler::ReliefLogger::logMemoryUsageChange()
 #define MEMORYPRESSURE_LOG(...) WTFLogAlways(__VA_ARGS__)
 #endif
 
-    size_t currentMemory = platformMemoryUsage();
-    if (currentMemory == static_cast<size_t>(-1) || m_initialMemory == static_cast<size_t>(-1)) {
+    auto currentMemory = platformMemoryUsage();
+    if (!currentMemory || !m_initialMemory) {
         MEMORYPRESSURE_LOG("Memory pressure relief: " STRING_SPECIFICATION ": (Unable to get dirty memory information for process)", m_logString);
         return;
     }
 
-    long memoryDiff = currentMemory - m_initialMemory;
-    if (memoryDiff < 0)
-        MEMORYPRESSURE_LOG("Memory pressure relief: " STRING_SPECIFICATION ": -dirty %ld bytes (from %zu to %zu)", m_logString, (memoryDiff * -1), m_initialMemory, currentMemory);
-    else if (memoryDiff > 0)
-        MEMORYPRESSURE_LOG("Memory pressure relief: " STRING_SPECIFICATION ": +dirty %ld bytes (from %zu to %zu)", m_logString, memoryDiff, m_initialMemory, currentMemory);
-    else
-        MEMORYPRESSURE_LOG("Memory pressure relief: " STRING_SPECIFICATION ": =dirty (at %zu bytes)", m_logString, currentMemory);
+    long residentDiff = currentMemory->resident - m_initialMemory->resident;
+    long physicalDiff = currentMemory->physical - m_initialMemory->physical;
+
+    MEMORYPRESSURE_LOG("Memory pressure relief: " STRING_SPECIFICATION ": res = %zu/%zu/%ld, res+swap = %zu/%zu/%ld",
+        m_logString,
+        m_initialMemory->resident, currentMemory->resident, residentDiff,
+        m_initialMemory->physical, currentMemory->physical, physicalDiff);
 }
 
 #if !PLATFORM(COCOA) && !OS(LINUX) && !PLATFORM(WIN)
@@ -96,7 +97,7 @@ void MemoryPressureHandler::uninstall() { }
 void MemoryPressureHandler::holdOff(unsigned) { }
 void MemoryPressureHandler::respondToMemoryPressure(Critical, Synchronous) { }
 void MemoryPressureHandler::platformReleaseMemory(Critical) { }
-size_t MemoryPressureHandler::ReliefLogger::platformMemoryUsage() { return 0; }
+std::optional<MemoryPressureHandler::ReliefLogger::MemoryUsage> MemoryPressureHandler::ReliefLogger::platformMemoryUsage() { return std::nullopt; }
 #endif
 
 } // namespace WebCore
index f9fd3a6..f86e9be 100644 (file)
@@ -33,6 +33,7 @@
 #include <wtf/FastMalloc.h>
 #include <wtf/Forward.h>
 #include <wtf/NeverDestroyed.h>
+#include <wtf/Optional.h>
 
 #if PLATFORM(IOS)
 #include <wtf/Lock.h>
@@ -90,34 +91,38 @@ public:
     public:
         explicit ReliefLogger(const char *log)
             : m_logString(log)
-#if !RELEASE_LOG_DISABLED
-            , m_initialMemory(platformMemoryUsage())
-#else
-            , m_initialMemory(s_loggingEnabled ? platformMemoryUsage() : 0)
-#endif
+            , m_initialMemory(loggingEnabled() ? platformMemoryUsage() : MemoryUsage { })
         {
         }
 
         ~ReliefLogger()
         {
-#if !RELEASE_LOG_DISABLED
-            logMemoryUsageChange();
-#else
-            if (s_loggingEnabled)
+            if (loggingEnabled())
                 logMemoryUsageChange();
-#endif
         }
 
+
         const char* logString() const { return m_logString; }
         static void setLoggingEnabled(bool enabled) { s_loggingEnabled = enabled; }
-        static bool loggingEnabled() { return s_loggingEnabled; }
+        static bool loggingEnabled()
+        {
+#if RELEASE_LOG_DISABLED
+            return s_loggingEnabled;
+#else
+            return true;
+#endif
+        }
 
     private:
-        size_t platformMemoryUsage();
+        struct MemoryUsage {
+            size_t resident { 0 };
+            size_t physical { 0 };
+        };
+        std::optional<MemoryUsage> platformMemoryUsage();
         void logMemoryUsageChange();
 
         const char* m_logString;
-        size_t m_initialMemory;
+        std::optional<MemoryUsage> m_initialMemory;
 
         WEBCORE_EXPORT static bool s_loggingEnabled;
     };
index 3bb1e0d..3eec7c7 100644 (file)
@@ -49,7 +49,6 @@ void MemoryPressureHandler::platformReleaseMemory(Critical critical)
     if (critical == Critical::Yes && (!isUnderMemoryPressure() || m_isSimulatingMemoryPressure)) {
         // libcache listens to OS memory notifications, but for process suspension
         // or memory pressure simulation, we need to prod it manually:
-        ReliefLogger log("Purging libcache caches");
         cache_simulate_memory_warning_event(DISPATCH_MEMORYPRESSURE_CRITICAL);
     }
 }
@@ -186,15 +185,15 @@ void MemoryPressureHandler::respondToMemoryPressure(Critical critical, Synchrono
 #endif
 }
 
-size_t MemoryPressureHandler::ReliefLogger::platformMemoryUsage()
+std::optional<MemoryPressureHandler::ReliefLogger::MemoryUsage> MemoryPressureHandler::ReliefLogger::platformMemoryUsage()
 {
     task_vm_info_data_t vmInfo;
     mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
     kern_return_t err = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
     if (err != KERN_SUCCESS)
-        return static_cast<size_t>(-1);
+        return std::nullopt;
 
-    return static_cast<size_t>(vmInfo.internal);
+    return MemoryUsage {static_cast<size_t>(vmInfo.internal), static_cast<size_t>(vmInfo.phys_footprint)};
 }
 
 #if PLATFORM(IOS)
index 421c616..4d33abf 100644 (file)
@@ -292,14 +292,13 @@ void MemoryPressureHandler::respondToMemoryPressure(Critical critical, Synchrono
 void MemoryPressureHandler::platformReleaseMemory(Critical)
 {
 #ifdef __GLIBC__
-    ReliefLogger log("Run malloc_trim");
     malloc_trim(0);
 #endif
 }
 
-size_t MemoryPressureHandler::ReliefLogger::platformMemoryUsage()
+std::optional<MemoryPressureHandler::ReliefLogger::MemoryUsage> MemoryPressureHandler::ReliefLogger::platformMemoryUsage()
 {
-    return processMemoryUsage();
+    return MemoryUsage {processMemoryUsage(), 0};
 }
 
 void MemoryPressureHandler::setMemoryPressureMonitorHandle(int fd)
index fc87b70..d1480df 100644 (file)
@@ -124,9 +124,9 @@ void MemoryPressureHandler::respondToMemoryPressure(Critical critical, Synchrono
     releaseMemory(critical, synchronous);
 }
 
-size_t MemoryPressureHandler::ReliefLogger::platformMemoryUsage()
+std::optional<MemoryPressureHandler::ReliefLogger::MemoryUsage> MemoryPressureHandler::ReliefLogger::platformMemoryUsage()
 {
-    return 0;
+    return std::nullopt;
 }
 
 } // namespace WebCore