Chromium Code Reviews| Index: content/browser/memory/memory_monitor_mac.cc |
| diff --git a/content/browser/memory/memory_monitor_mac.cc b/content/browser/memory/memory_monitor_mac.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..14afd2fa3362d6053c57aef67bf7aab1090b1f21 |
| --- /dev/null |
| +++ b/content/browser/memory/memory_monitor_mac.cc |
| @@ -0,0 +1,106 @@ |
| +// Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/memory/memory_monitor_mac.h" |
| + |
| +#include <math.h> |
| +#include <sys/sysctl.h> |
| + |
| +#include <algorithm> |
| + |
| +#include "base/memory/ptr_util.h" |
| +#include "base/process/process_metrics.h" |
| +#include "content/browser/memory/memory_coordinator.h" |
| + |
| +namespace content { |
| + |
| +namespace { |
| + |
| +// The number of bits to shift to convert KiB to MiB. |
| +const int kShiftKiBtoMiB = 10; |
| + |
| +// The rate at which to adjust the "critical" boundary, in MiB/s. |
| +const int kCriticalAdjustmentMBS = 1; |
| + |
| +} // namespace |
| + |
| +MemoryMonitorMac::MemoryMonitorMac(MemoryMonitorDelegate* delegate, |
| + base::TimeDelta poll_interval) |
| + : delegate_(delegate), |
| + poll_interval_adjustment_mb_(poll_interval.InSeconds() * |
| + kCriticalAdjustmentMBS), |
| + critical_free_mb_(0) { |
| + // Poll interval has to be at least 1s. |
| + DCHECK_LE(1, poll_interval.InSeconds()); |
| +} |
| + |
| +MemoryMonitorMac::~MemoryMonitorMac() {} |
| + |
| +int MemoryMonitorMac::GetFreeMemoryUntilCriticalMB() { |
| + // Get the amount of free memory in the system. The "free" amount is a poor |
| + // indication because it doesn't take into consideration memory that is |
| + // in use but can be easily freed, such as disk buffers. |
| + base::SystemMemoryInfoKB mem_info = {}; |
| + delegate_->GetSystemMemoryInfo(&mem_info); |
| + int free_mem = mem_info.free >> kShiftKiBtoMiB; |
| + |
| + // Get the current system memory pressure. |
| + int mac_memory_pressure; |
| + bool success = delegate_->GetSystemMemoryPressure(&mac_memory_pressure); |
| + DCHECK(success); |
| + |
| + // Adjust the "critical threshold" according to current memory pressure. |
| + switch (mac_memory_pressure) { |
| + case DISPATCH_MEMORYPRESSURE_NORMAL: |
| + // Under normal operation, allow more and more memory to be used. |
| + critical_free_mb_ = |
| + std::max(0LL, critical_free_mb_ - poll_interval_adjustment_mb_); |
| + break; |
| + case DISPATCH_MEMORYPRESSURE_WARN: { |
| + // Once free memory starts to get low, gradually reduce the amount |
| + // of memory that con be used. |
| + int half_free = free_mem >> 1; |
| + if (critical_free_mb_ < half_free) |
| + critical_free_mb_ = half_free; |
|
chrisha
2016/11/09 21:21:11
Do we have a reason to believe that 50% is the rig
bcwhite
2016/11/09 22:46:54
None at all. Just seemed a reasonable starting gu
chrisha
2016/11/14 18:14:31
Do you have an idea for how we could monitor the p
bcwhite
2016/11/15 23:15:09
I could create a metric that counts the number of
|
| + else if (critical_free_mb_ < free_mem) |
| + critical_free_mb_ += poll_interval_adjustment_mb_; |
| + } break; |
| + case DISPATCH_MEMORYPRESSURE_CRITICAL: |
| + // When memory pressure is critical, assume that system is about to swap. |
| + critical_free_mb_ = free_mem; |
|
chrisha
2016/11/09 21:21:11
Shouldn't this be *zero*? Critical is defined as s
bcwhite
2016/11/09 22:46:54
Critical is defined as the amount of memory that c
chrisha
2016/11/14 18:14:31
Ah, okay, makes sense.
|
| + break; |
| + } |
| + |
| + // Return the amount of memory until critical. |
| + return free_mem - critical_free_mb_; |
| +} |
| + |
| +// static |
| +std::unique_ptr<MemoryMonitorMac> MemoryMonitorMac::Create( |
| + MemoryMonitorDelegate* delegate, |
| + base::TimeDelta poll_interval) { |
| + return base::MakeUnique<MemoryMonitorMac>(delegate, poll_interval); |
| +} |
| + |
| +// Implementation of factory function defined in memory_monitor.h. |
| +std::unique_ptr<MemoryMonitor> CreateMemoryMonitor() { |
| + return MemoryMonitorMac::Create( |
| + MemoryMonitorMacDelegate::GetInstance(), |
| + MemoryCoordinator::GetInstance()->GetMonitoringInterval()); |
| +} |
| + |
| +MemoryMonitorMacDelegate* MemoryMonitorMacDelegate::GetInstance() { |
| + return base::Singleton< |
| + MemoryMonitorMacDelegate, |
| + base::LeakySingletonTraits<MemoryMonitorMacDelegate>>::get(); |
| +} |
| + |
| +bool MemoryMonitorMacDelegate::GetSystemMemoryPressure(int* mem_pressure) { |
| + size_t length = sizeof(*mem_pressure); |
| + sysctlbyname("kern.memorystatus_vm_pressure_level", mem_pressure, &length, |
| + nullptr, 0); |
| + return true; |
| +} |
| + |
| +} // namespace content |