Index: content/child/memory/child_memory_message_filter.cc |
diff --git a/content/child/memory/child_memory_message_filter.cc b/content/child/memory/child_memory_message_filter.cc |
index 91e6849eab2eb2aea5d157e6ef42ee85aa0ce031..726c7c2d59ac7ccbb2af6dbe17bf52ee33549d02 100644 |
--- a/content/child/memory/child_memory_message_filter.cc |
+++ b/content/child/memory/child_memory_message_filter.cc |
@@ -4,11 +4,60 @@ |
#include "content/child/memory/child_memory_message_filter.h" |
+#include "base/metrics/histogram_macros.h" |
+#include "base/process/process_metrics.h" |
#include "content/common/memory_messages.h" |
namespace content { |
-ChildMemoryMessageFilter::ChildMemoryMessageFilter() {} |
+namespace { |
+ |
+// The memory pressure monitoring is OSX only because as of this writing a good |
+// estimate of wired pages is lacking on Windows. The number of desktop Linux |
+// users doesn't warrant a special implementation for that, and ChromeOS and |
+// Android generally handle memory pressure differently. |
+#if defined(OS_MACOSX) |
+ |
+// Returns an estimate of the physical memory used by the current process. |
+// This is not hooked up on all platforms, it will return 0 if unsupported. |
+uint64_t GetPrivateMemoryBytes() { |
+ std::unique_ptr<base::ProcessMetrics> metrics = base::ProcessMetrics::CreateCurrentProcessMetrics(); |
+ |
+ base::ProcessMetrics::TaskVMInfo info = metrics->GetTaskVMInfo(); |
+ // This value is only nonzero on OSX 10.12 and above. |
+ return info.phys_footprint; |
+} |
+ |
+// Logs a histogram of the memory saved from a pressure event. This is called |
+// on a timer to allow some time for pressure events to get propagated to other |
+// threads or asynchronous cleanup tasks to occur. |
+void LogMemoryPressureDelta(uint64_t before_memory) { |
+ uint64_t after_memory = GetPrivateMemoryBytes(); |
+ |
+ UMA_HISTOGRAM_MEMORY_KB("Memory.RendererPressureSavingsKB", |
+ (before_memory - after_memory) / 1024); |
+ |
+ double savings_frac = 1.0 - |
+ (static_cast<double>(after_memory) / static_cast<double>(before_memory)); |
+ |
+ // The histogram macros can't handle negative items well, as 0 will always be |
+ // the underflow bucket. If memory increased, it's unlikely to be a result |
+ // of compaction so we don't care too much about the specific value. |
+ if (savings_frac < 0.0) |
+ savings_frac = 0.0; |
+ UMA_HISTOGRAM_PERCENTAGE("Memory.RendererPressurePercentSavings", |
+ static_cast<int>(100.0 * savings_frac)); |
+} |
+ |
+#endif // OS_MACOSX |
+ |
+} // namespace |
+ |
+ChildMemoryMessageFilter::ChildMemoryMessageFilter() |
+#if defined(OS_MACOSX) |
+ : pressure_timer_(false, false) |
+#endif |
+{} |
ChildMemoryMessageFilter::~ChildMemoryMessageFilter() {} |
@@ -40,9 +89,20 @@ void ChildMemoryMessageFilter::OnSimulatePressureNotification( |
void ChildMemoryMessageFilter::OnPressureNotification( |
base::MemoryPressureListener::MemoryPressureLevel level) { |
+#if defined(OS_MACOSX) |
+ uint64_t before_memory = GetPrivateMemoryBytes(); |
+#endif // OS_MACOSX |
+ |
// Forward the message along the normal notification path. If notifications |
// are suppressed then the notification will be swallowed. |
base::MemoryPressureListener::NotifyMemoryPressure(level); |
+ |
+#if defined(OS_MACOSX) |
+ if (before_memory > 0) { |
+ pressure_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5), |
+ base::BindRepeating(&LogMemoryPressureDelta, before_memory)); |
+ } |
+#endif // OS_MACOSX |
} |
} // namespace content |