| 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
|
|
|