Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1107)

Unified Diff: base/memory/memory_pressure_monitor_linux.cc

Issue 1250093006: Added memory pressure monitor for linux. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Uncomment ::Get functionality Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/memory/memory_pressure_monitor_linux.cc
diff --git a/base/memory/memory_pressure_monitor_chromeos.cc b/base/memory/memory_pressure_monitor_linux.cc
similarity index 39%
copy from base/memory/memory_pressure_monitor_chromeos.cc
copy to base/memory/memory_pressure_monitor_linux.cc
index 640e4633fd51c7cb9d3e820af18c62a17ea14f0b..7034e14b7cacd7ed9a327b9febb13a892d025c26 100644
--- a/base/memory/memory_pressure_monitor_chromeos.cc
+++ b/base/memory/memory_pressure_monitor_linux.cc
@@ -1,21 +1,16 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2015 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 "base/memory/memory_pressure_monitor_chromeos.h"
-
-#include <fcntl.h>
-#include <sys/select.h>
+#include "base/memory/memory_pressure_monitor.h"
#include "base/metrics/histogram_macros.h"
-#include "base/posix/eintr_wrapper.h"
#include "base/process/process_metrics.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
namespace base {
-namespace chromeos {
namespace {
@@ -33,91 +28,44 @@ const int kModerateMemoryPressureCooldown =
// Threshold constants to emit pressure events.
const int kNormalMemoryPressureModerateThresholdPercent = 60;
const int kNormalMemoryPressureCriticalThresholdPercent = 95;
-const int kAggressiveMemoryPressureModerateThresholdPercent = 35;
-const int kAggressiveMemoryPressureCriticalThresholdPercent = 70;
// The possible state for memory pressure level. The values should be in line
// with values in MemoryPressureListener::MemoryPressureLevel and should be
// updated if more memory pressure levels are introduced.
enum MemoryPressureLevelUMA {
- MEMORY_PRESSURE_LEVEL_NONE = 0,
- MEMORY_PRESSURE_LEVEL_MODERATE,
- MEMORY_PRESSURE_LEVEL_CRITICAL,
- NUM_MEMORY_PRESSURE_LEVELS
+ UMA_MEMORY_PRESSURE_LEVEL_NONE = 0,
+ UMA_MEMORY_PRESSURE_LEVEL_MODERATE = 1,
+ UMA_MEMORY_PRESSURE_LEVEL_CRITICAL = 2,
+ // This must be the last value in the enum.
+ UMA_MEMORY_PRESSURE_LEVEL_COUNT,
};
-// This is the file that will exist if low memory notification is available
-// on the device. Whenever it becomes readable, it signals a low memory
-// condition.
-const char kLowMemFile[] = "/dev/chromeos-low-mem";
-
-// Converts a |MemoryPressureThreshold| value into a used memory percentage for
-// the moderate pressure event.
-int GetModerateMemoryThresholdInPercent(
- MemoryPressureMonitor::MemoryPressureThresholds thresholds) {
- return thresholds == MemoryPressureMonitor::
- THRESHOLD_AGGRESSIVE_CACHE_DISCARD ||
- thresholds == MemoryPressureMonitor::THRESHOLD_AGGRESSIVE
- ? kAggressiveMemoryPressureModerateThresholdPercent
- : kNormalMemoryPressureModerateThresholdPercent;
-}
-
-// Converts a |MemoryPressureThreshold| value into a used memory percentage for
-// the critical pressure event.
-int GetCriticalMemoryThresholdInPercent(
- MemoryPressureMonitor::MemoryPressureThresholds thresholds) {
- return thresholds == MemoryPressureMonitor::
- THRESHOLD_AGGRESSIVE_TAB_DISCARD ||
- thresholds == MemoryPressureMonitor::THRESHOLD_AGGRESSIVE
- ? kAggressiveMemoryPressureCriticalThresholdPercent
- : kNormalMemoryPressureCriticalThresholdPercent;
-}
-
// Converts free percent of memory into a memory pressure value.
MemoryPressureListener::MemoryPressureLevel GetMemoryPressureLevelFromFillLevel(
- int actual_fill_level,
- int moderate_threshold,
- int critical_threshold) {
- if (actual_fill_level < moderate_threshold)
+ int actual_fill_level) {
+ if (actual_fill_level < kNormalMemoryPressureModerateThresholdPercent)
return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
- return actual_fill_level < critical_threshold
+ return actual_fill_level < kNormalMemoryPressureCriticalThresholdPercent
? MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE
: MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
}
-
-// This function will be called less then once a second. It will check if
-// the kernel has detected a low memory situation.
-bool IsLowMemoryCondition(int file_descriptor) {
- fd_set fds;
- struct timeval tv;
-
- FD_ZERO(&fds);
- FD_SET(file_descriptor, &fds);
-
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- return HANDLE_EINTR(select(file_descriptor + 1, &fds, NULL, NULL, &tv)) > 0;
-}
-
} // namespace
-MemoryPressureMonitor::MemoryPressureMonitor(
- MemoryPressureThresholds thresholds)
+MemoryPressureMonitor::MemoryPressureMonitor()
: current_memory_pressure_level_(
MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE),
moderate_pressure_repeat_count_(0),
- moderate_pressure_threshold_percent_(
- GetModerateMemoryThresholdInPercent(thresholds)),
- critical_pressure_threshold_percent_(
- GetCriticalMemoryThresholdInPercent(thresholds)),
- low_mem_file_(HANDLE_EINTR(::open(kLowMemFile, O_RDONLY))),
weak_ptr_factory_(this) {
+ DCHECK(!g_monitor);
+ g_monitor = this;
+
StartObserving();
- LOG_IF(ERROR, !low_mem_file_.is_valid()) << "Cannot open kernel listener";
}
MemoryPressureMonitor::~MemoryPressureMonitor() {
+ DCHECK(g_monitor);
+ g_monitor = nullptr;
+
StopObserving();
}
@@ -132,18 +80,11 @@ MemoryPressureMonitor::GetCurrentPressureLevel() const {
return current_memory_pressure_level_;
}
-// static
-MemoryPressureMonitor* MemoryPressureMonitor::Get() {
- return static_cast<MemoryPressureMonitor*>(
- base::MemoryPressureMonitor::Get());
-}
-
void MemoryPressureMonitor::StartObserving() {
- timer_.Start(FROM_HERE,
- TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs),
- Bind(&MemoryPressureMonitor::
- CheckMemoryPressureAndRecordStatistics,
- weak_ptr_factory_.GetWeakPtr()));
+ timer_.Start(
+ FROM_HERE, TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs),
+ Bind(&MemoryPressureMonitor::CheckMemoryPressureAndRecordStatistics,
+ weak_ptr_factory_.GetWeakPtr()));
}
void MemoryPressureMonitor::StopObserving() {
@@ -155,72 +96,49 @@ void MemoryPressureMonitor::CheckMemoryPressureAndRecordStatistics() {
CheckMemoryPressure();
// Record UMA histogram statistics for the current memory pressure level.
- MemoryPressureLevelUMA memory_pressure_level_uma(MEMORY_PRESSURE_LEVEL_NONE);
+ MemoryPressureLevelUMA memory_pressure_level_uma(
+ UMA_MEMORY_PRESSURE_LEVEL_NONE);
switch (current_memory_pressure_level_) {
case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
- memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_NONE;
+ memory_pressure_level_uma = UMA_MEMORY_PRESSURE_LEVEL_NONE;
break;
case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
- memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_MODERATE;
+ memory_pressure_level_uma = UMA_MEMORY_PRESSURE_LEVEL_MODERATE;
break;
case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
- memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_CRITICAL;
+ memory_pressure_level_uma = UMA_MEMORY_PRESSURE_LEVEL_CRITICAL;
break;
}
- UMA_HISTOGRAM_ENUMERATION("ChromeOS.MemoryPressureLevel",
- memory_pressure_level_uma,
- NUM_MEMORY_PRESSURE_LEVELS);
+ UMA_HISTOGRAM_ENUMERATION("Memory.PressureLevel", memory_pressure_level_uma,
+ UMA_MEMORY_PRESSURE_LEVEL_COUNT);
}
void MemoryPressureMonitor::CheckMemoryPressure() {
MemoryPressureListener::MemoryPressureLevel old_pressure =
current_memory_pressure_level_;
-
- // If we have the kernel low memory observer, we use it's flag instead of our
- // own computation (for now). Note that in "simulation mode" it can be null.
- // TODO(skuhne): We need to add code which makes sure that the kernel and this
- // computation come to similar results and then remove this override again.
- // TODO(skuhne): Add some testing framework here to see how close the kernel
- // and the internal functions are.
- if (low_mem_file_.is_valid() && IsLowMemoryCondition(low_mem_file_.get())) {
- current_memory_pressure_level_ =
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
- } else {
- current_memory_pressure_level_ = GetMemoryPressureLevelFromFillLevel(
- GetUsedMemoryInPercent(),
- moderate_pressure_threshold_percent_,
- critical_pressure_threshold_percent_);
-
- // When listening to the kernel, we ignore the reported memory pressure
- // level from our own computation and reduce critical to moderate.
- if (low_mem_file_.is_valid() &&
- current_memory_pressure_level_ ==
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
- current_memory_pressure_level_ =
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE;
- }
- }
+ current_memory_pressure_level_ =
+ GetMemoryPressureLevelFromFillLevel(GetUsedMemoryInPercent());
// In case there is no memory pressure we do not notify.
if (current_memory_pressure_level_ ==
MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
return;
}
+
if (old_pressure == current_memory_pressure_level_) {
// If the memory pressure is still at the same level, we notify again for a
// critical level. In case of a moderate level repeat however, we only send
// a notification after a certain time has passed.
if (current_memory_pressure_level_ ==
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE &&
- ++moderate_pressure_repeat_count_ <
- kModerateMemoryPressureCooldown) {
+ MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE &&
+ ++moderate_pressure_repeat_count_ < kModerateMemoryPressureCooldown) {
return;
}
} else if (current_memory_pressure_level_ ==
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE &&
+ MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE &&
old_pressure ==
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
+ MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
// When we reducing the pressure level from critical to moderate, we
// restart the timeout and do not send another notification.
moderate_pressure_repeat_count_ = 0;
@@ -230,43 +148,22 @@ void MemoryPressureMonitor::CheckMemoryPressure() {
MemoryPressureListener::NotifyMemoryPressure(current_memory_pressure_level_);
}
-// Gets the used ChromeOS memory in percent.
+// Gets the used memory in percent.
int MemoryPressureMonitor::GetUsedMemoryInPercent() {
base::SystemMemoryInfoKB info;
if (!base::GetSystemMemoryInfo(&info)) {
VLOG(1) << "Cannot determine the free memory of the system.";
return 0;
}
- // TODO(skuhne): Instead of adding the kernel memory pressure calculation
- // logic here, we should have a kernel mechanism similar to the low memory
- // notifier in ChromeOS which offers multiple pressure states.
- // To track this, we have crbug.com/381196.
-
- // The available memory consists of "real" and virtual (z)ram memory.
- // Since swappable memory uses a non pre-deterministic compression and
- // the compression creates its own "dynamic" in the system, it gets
- // de-emphasized by the |kSwapWeight| factor.
- const int kSwapWeight = 4;
-
- // The total memory we have is the "real memory" plus the virtual (z)ram.
- int total_memory = info.total + info.swap_total / kSwapWeight;
-
- // The kernel internally uses 50MB.
- const int kMinFileMemory = 50 * 1024;
-
- // Most file memory can be easily reclaimed.
- int file_memory = info.active_file + info.inactive_file;
- // unless it is dirty or it's a minimal portion which is required.
- file_memory -= info.dirty + kMinFileMemory;
- // Available memory is the sum of free, swap and easy reclaimable memory.
- int available_memory =
- info.free + info.swap_free / kSwapWeight + file_memory;
+ // Cast to int64 to avoid integer overflows when calculating the percentage.
+ int64 total_memory = info.total;
+ int64 available_memory = info.free;
DCHECK(available_memory < total_memory);
- int percentage = ((total_memory - available_memory) * 100) / total_memory;
+ int percentage = static_cast<int>(((total_memory - available_memory) * 100) /
+ total_memory);
return percentage;
}
-} // namespace chromeos
} // namespace base
« no previous file with comments | « base/memory/memory_pressure_monitor_chromeos_unittest.cc ('k') | base/memory/memory_pressure_monitor_linux_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698