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