Add memory footprint reporting using diagnostic logging.
authorakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Jan 2017 00:15:00 +0000 (00:15 +0000)
committerakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Jan 2017 00:15:00 +0000 (00:15 +0000)
<https://webkit.org/b/167285>
<rdar://problem/30151767>

Reviewed by Chris Dumez.

Add some basic logging of physical memory footprint post-load and post-backgrounding.
The logging works similarly to the CPU usage logging, though with slightly longer
delays to allow the measurement to stabilize.

* page/DiagnosticLoggingKeys.cpp:
(WebCore::DiagnosticLoggingKeys::memoryUsageKey):
(WebCore::DiagnosticLoggingKeys::memoryUsageToDiagnosticLoggingKey):
* page/DiagnosticLoggingKeys.h:
* page/PerformanceLogging.cpp:
(WebCore::PerformanceLogging::physicalFootprint):
* page/PerformanceLogging.h:
* page/PerformanceMonitor.cpp:
(WebCore::PerformanceMonitor::PerformanceMonitor):
(WebCore::PerformanceMonitor::didFinishLoad):
(WebCore::PerformanceMonitor::activityStateChanged):
(WebCore::PerformanceMonitor::measurePostLoadMemoryUsage):
(WebCore::PerformanceMonitor::measurePostBackgroundingMemoryUsage):
* page/PerformanceMonitor.h:
* page/Settings.h:
(WebCore::Settings::isPostLoadMemoryUsageMeasurementEnabled):
(WebCore::Settings::isPostBackgroundingMemoryUsageMeasurementEnabled):
* page/cocoa/PerformanceLoggingCocoa.mm:
(WebCore::PerformanceLogging::physicalFootprint):

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

Source/WebCore/ChangeLog
Source/WebCore/page/DiagnosticLoggingKeys.cpp
Source/WebCore/page/DiagnosticLoggingKeys.h
Source/WebCore/page/PerformanceLogging.cpp
Source/WebCore/page/PerformanceLogging.h
Source/WebCore/page/PerformanceMonitor.cpp
Source/WebCore/page/PerformanceMonitor.h
Source/WebCore/page/Settings.h
Source/WebCore/page/cocoa/PerformanceLoggingCocoa.mm

index 7dae011..fc47d30 100644 (file)
@@ -1,3 +1,35 @@
+2017-01-24  Andreas Kling  <akling@apple.com>
+
+        Add memory footprint reporting using diagnostic logging.
+        <https://webkit.org/b/167285>
+        <rdar://problem/30151767>
+
+        Reviewed by Chris Dumez.
+
+        Add some basic logging of physical memory footprint post-load and post-backgrounding.
+        The logging works similarly to the CPU usage logging, though with slightly longer
+        delays to allow the measurement to stabilize.
+
+        * page/DiagnosticLoggingKeys.cpp:
+        (WebCore::DiagnosticLoggingKeys::memoryUsageKey):
+        (WebCore::DiagnosticLoggingKeys::memoryUsageToDiagnosticLoggingKey):
+        * page/DiagnosticLoggingKeys.h:
+        * page/PerformanceLogging.cpp:
+        (WebCore::PerformanceLogging::physicalFootprint):
+        * page/PerformanceLogging.h:
+        * page/PerformanceMonitor.cpp:
+        (WebCore::PerformanceMonitor::PerformanceMonitor):
+        (WebCore::PerformanceMonitor::didFinishLoad):
+        (WebCore::PerformanceMonitor::activityStateChanged):
+        (WebCore::PerformanceMonitor::measurePostLoadMemoryUsage):
+        (WebCore::PerformanceMonitor::measurePostBackgroundingMemoryUsage):
+        * page/PerformanceMonitor.h:
+        * page/Settings.h:
+        (WebCore::Settings::isPostLoadMemoryUsageMeasurementEnabled):
+        (WebCore::Settings::isPostBackgroundingMemoryUsageMeasurementEnabled):
+        * page/cocoa/PerformanceLoggingCocoa.mm:
+        (WebCore::PerformanceLogging::physicalFootprint):
+
 2017-01-24  Joseph Pecoraro  <pecoraro@apple.com>
 
         Remove always true unsafePluginPastingEnabled setting
index 18b832d..5ed46e3 100644 (file)
@@ -328,6 +328,11 @@ String DiagnosticLoggingKeys::cpuUsageKey()
     return ASCIILiteral("cpuUsage");
 }
 
+String DiagnosticLoggingKeys::memoryUsageKey()
+{
+    return ASCIILiteral("memoryUsage");
+}
+
 String DiagnosticLoggingKeys::createSharedBufferFailedKey()
 {
     return ASCIILiteral("createSharedBufferFailed");
@@ -673,6 +678,33 @@ String WebCore::DiagnosticLoggingKeys::webGLKey()
     return ASCIILiteral("webGL");
 }
 
+String DiagnosticLoggingKeys::memoryUsageToDiagnosticLoggingKey(uint64_t memoryUsage)
+{
+    if (memoryUsage < 32 * MB)
+        return ASCIILiteral("below32");
+    if (memoryUsage < 64 * MB)
+        return ASCIILiteral("32to64");
+    if (memoryUsage < 128 * MB)
+        return ASCIILiteral("64to128");
+    if (memoryUsage < 256 * MB)
+        return ASCIILiteral("128to256");
+    if (memoryUsage < 512 * MB)
+        return ASCIILiteral("256to512");
+    if (memoryUsage < 1024 * MB)
+        return ASCIILiteral("512to1024");
+    if (memoryUsage < 2048 * MB)
+        return ASCIILiteral("1024to2048");
+    if (memoryUsage < 4096llu * MB)
+        return ASCIILiteral("2048to4096");
+    if (memoryUsage < 8192llu * MB)
+        return ASCIILiteral("4096to8192");
+    if (memoryUsage < 16384llu * MB)
+        return ASCIILiteral("8192to16384");
+    if (memoryUsage < 32768llu * MB)
+        return ASCIILiteral("16384to32768");
+    return ASCIILiteral("over32768");
+}
+
 String DiagnosticLoggingKeys::foregroundCPUUsageToDiagnosticLoggingKey(double cpuUsage)
 {
     if (cpuUsage < 10)
index 50897bb..9f250a9 100644 (file)
@@ -41,6 +41,7 @@ public:
     static String canCacheKey();
     static String cannotSuspendActiveDOMObjectsKey();
     WEBCORE_EXPORT static String cpuUsageKey();
+    WEBCORE_EXPORT static String memoryUsageKey();
     WEBCORE_EXPORT static String createSharedBufferFailedKey();
     WEBCORE_EXPORT static String deltaKey();
     static String deniedByClientKey();
@@ -159,6 +160,7 @@ public:
     WEBCORE_EXPORT static String webViewKey();
     WEBCORE_EXPORT static String zoomedKey();
 
+    WEBCORE_EXPORT static String memoryUsageToDiagnosticLoggingKey(uint64_t memoryUsage);
     WEBCORE_EXPORT static String foregroundCPUUsageToDiagnosticLoggingKey(double cpuUsage);
     WEBCORE_EXPORT static String backgroundCPUUsageToDiagnosticLoggingKey(double cpuUsage);
 
index a403c98..34af678 100644 (file)
@@ -103,6 +103,7 @@ void PerformanceLogging::didReachPointOfInterest(PointOfInterest poi)
 
 #if !PLATFORM(COCOA)
 void PerformanceLogging::getPlatformMemoryUsageStatistics(HashMap<const char*, size_t>&) { }
+std::optional<uint64_t> PerformanceLogging::physicalFootprint() { return std::nullopt; }
 #endif
 
 }
index 9f8ccc1..9287a29 100644 (file)
@@ -49,6 +49,7 @@ public:
 
     WEBCORE_EXPORT static HashCountedSet<const char*> javaScriptObjectCounts();
     WEBCORE_EXPORT static HashMap<const char*, size_t> memoryUsageStatistics(ShouldIncludeExpensiveComputations);
+    WEBCORE_EXPORT static std::optional<uint64_t> physicalFootprint();
 
 private:
     static void getPlatformMemoryUsageStatistics(HashMap<const char*, size_t>&);
index 2caebef..4e86544 100644 (file)
@@ -32,6 +32,7 @@
 #include "DiagnosticLoggingKeys.h"
 #include "Logging.h"
 #include "Page.h"
+#include "PerformanceLogging.h"
 #include "Settings.h"
 
 namespace WebCore {
@@ -43,6 +44,8 @@ static const std::chrono::seconds postLoadCPUUsageMeasurementDuration { 10 };
 static const std::chrono::minutes backgroundCPUUsageMeasurementDuration { 5 };
 static const std::chrono::minutes cpuUsageSamplingInterval { 10 };
 
+static const std::chrono::seconds memoryUsageMeasurementDelay { 10 };
+
 static inline ActivityStateForCPUSampling activityStateForCPUSampling(ActivityState::Flags state)
 {
     if (!(state & ActivityState::IsVisible))
@@ -57,6 +60,8 @@ PerformanceMonitor::PerformanceMonitor(Page& page)
     , m_postPageLoadCPUUsageTimer(*this, &PerformanceMonitor::measurePostLoadCPUUsage)
     , m_postBackgroundingCPUUsageTimer(*this, &PerformanceMonitor::measurePostBackgroundingCPUUsage)
     , m_perActivityStateCPUUsageTimer(*this, &PerformanceMonitor::measurePerActivityStateCPUUsage)
+    , m_postPageLoadMemoryUsageTimer(*this, &PerformanceMonitor::measurePostLoadMemoryUsage)
+    , m_postBackgroundingMemoryUsageTimer(*this, &PerformanceMonitor::measurePostBackgroundingMemoryUsage)
 {
     ASSERT(!page.isUtilityPage());
 
@@ -70,6 +75,7 @@ void PerformanceMonitor::didStartProvisionalLoad()
 {
     m_postLoadCPUTime = std::nullopt;
     m_postPageLoadCPUUsageTimer.stop();
+    m_postPageLoadMemoryUsageTimer.stop();
 }
 
 void PerformanceMonitor::didFinishLoad()
@@ -79,6 +85,10 @@ void PerformanceMonitor::didFinishLoad()
         m_postLoadCPUTime = std::nullopt;
         m_postPageLoadCPUUsageTimer.startOneShot(cpuUsageMeasurementDelay);
     }
+
+    // Likewise for post-load memory usage measurement.
+    if (Settings::isPostLoadMemoryUsageMeasurementEnabled() && m_page.isOnlyNonUtilityPage())
+        m_postPageLoadMemoryUsageTimer.startOneShot(memoryUsageMeasurementDelay);
 }
 
 void PerformanceMonitor::activityStateChanged(ActivityState::Flags oldState, ActivityState::Flags newState)
@@ -103,6 +113,13 @@ void PerformanceMonitor::activityStateChanged(ActivityState::Flags oldState, Act
             m_perActivityStateCPUUsageTimer.startRepeating(cpuUsageSamplingInterval);
         }
     }
+
+    if (Settings::isPostBackgroundingMemoryUsageMeasurementEnabled() && visibilityChanged) {
+        if (newState & ActivityState::IsVisible)
+            m_postBackgroundingMemoryUsageTimer.stop();
+        else if (m_page.isOnlyNonUtilityPage())
+            m_postBackgroundingMemoryUsageTimer.startOneShot(memoryUsageMeasurementDelay);
+    }
 }
 
 void PerformanceMonitor::measurePostLoadCPUUsage()
@@ -127,6 +144,32 @@ void PerformanceMonitor::measurePostLoadCPUUsage()
     m_page.diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::postPageLoadKey(), DiagnosticLoggingKeys::cpuUsageKey(), DiagnosticLoggingKeys::foregroundCPUUsageToDiagnosticLoggingKey(cpuUsage), ShouldSample::No);
 }
 
+void PerformanceMonitor::measurePostLoadMemoryUsage()
+{
+    if (!m_page.isOnlyNonUtilityPage())
+        return;
+
+    std::optional<uint64_t> memoryUsage = PerformanceLogging::physicalFootprint();
+    if (!memoryUsage)
+        return;
+
+    RELEASE_LOG_IF_ALLOWED(PerformanceLogging, "measurePostLoadMemoryUsage: Process was using %llu bytes of memory after the page load.", memoryUsage.value());
+    m_page.diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::postPageLoadKey(), DiagnosticLoggingKeys::memoryUsageKey(), DiagnosticLoggingKeys::memoryUsageToDiagnosticLoggingKey(memoryUsage.value()), ShouldSample::No);
+}
+
+void PerformanceMonitor::measurePostBackgroundingMemoryUsage()
+{
+    if (!m_page.isOnlyNonUtilityPage())
+        return;
+
+    std::optional<uint64_t> memoryUsage = PerformanceLogging::physicalFootprint();
+    if (!memoryUsage)
+        return;
+
+    RELEASE_LOG_IF_ALLOWED(PerformanceLogging, "measurePostBackgroundingMemoryUsage: Process was using %llu bytes of memory after becoming non visible.", memoryUsage.value());
+    m_page.diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::postPageBackgroundingKey(), DiagnosticLoggingKeys::memoryUsageKey(), DiagnosticLoggingKeys::memoryUsageToDiagnosticLoggingKey(memoryUsage.value()), ShouldSample::No);
+}
+
 void PerformanceMonitor::measurePostBackgroundingCPUUsage()
 {
     if (!m_page.isOnlyNonUtilityPage()) {
index 60cac00..b89fa0d 100644 (file)
@@ -48,6 +48,9 @@ private:
     void measurePerActivityStateCPUUsage();
     void measureCPUUsageInActivityState(ActivityStateForCPUSampling);
 
+    void measurePostLoadMemoryUsage();
+    void measurePostBackgroundingMemoryUsage();
+
     Page& m_page;
 
     Timer m_postPageLoadCPUUsageTimer;
@@ -56,6 +59,9 @@ private:
     std::optional<CPUTime> m_postBackgroundingCPUTime;
     Timer m_perActivityStateCPUUsageTimer;
     std::optional<CPUTime> m_perActivityStateCPUTime;
+
+    Timer m_postPageLoadMemoryUsageTimer;
+    Timer m_postBackgroundingMemoryUsageTimer;
 };
 
 }
index 2d3c83c..7fc5708 100644 (file)
@@ -203,6 +203,9 @@ public:
     static bool isPostBackgroundingCPUUsageMeasurementEnabled();
     static bool isPerActivityStateCPUUsageMeasurementEnabled();
 
+    static bool isPostLoadMemoryUsageMeasurementEnabled();
+    static bool isPostBackgroundingMemoryUsageMeasurementEnabled();
+
     static bool globalConstRedeclarationShouldThrow();
 
     WEBCORE_EXPORT void setBackgroundShouldExtendBeyondPage(bool);
@@ -451,4 +454,22 @@ inline bool Settings::isPerActivityStateCPUUsageMeasurementEnabled()
 #endif
 }
 
+inline bool Settings::isPostLoadMemoryUsageMeasurementEnabled()
+{
+#if PLATFORM(COCOA)
+    return true;
+#else
+    return false;
+#endif
+}
+
+inline bool Settings::isPostBackgroundingMemoryUsageMeasurementEnabled()
+{
+#if PLATFORM(MAC)
+    return true;
+#else
+    return false;
+#endif
+}
+
 } // namespace WebCore
index fcde55b..2896fe1 100644 (file)
 
 namespace WebCore {
 
+std::optional<uint64_t> PerformanceLogging::physicalFootprint()
+{
+    task_vm_info_data_t vmInfo;
+    mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
+    kern_return_t result = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
+    if (result != KERN_SUCCESS)
+        return std::nullopt;
+    return vmInfo.phys_footprint;
+}
+
 void PerformanceLogging::getPlatformMemoryUsageStatistics(HashMap<const char*, size_t>& stats)
 {
     task_vm_info_data_t vmInfo;