Index: base/chromeos/memory_pressure_observer_chromeos.cc |
diff --git a/base/chromeos/memory_pressure_observer_chromeos.cc b/base/chromeos/memory_pressure_observer_chromeos.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d991e3f16b10fa0709bf7141aaed7ac61e6d6c38 |
--- /dev/null |
+++ b/base/chromeos/memory_pressure_observer_chromeos.cc |
@@ -0,0 +1,116 @@ |
+// Copyright 2014 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/chromeos/memory_pressure_observer_chromeos.h" |
+ |
+#include "base/process/process_metrics.h" |
+#include "base/time/time.h" |
+ |
+namespace base { |
+ |
+namespace { |
+ |
+// The time between memory pressure checks. |
+const int kMemoryPressureIntervalInMS = 1000; |
+ |
+// Converts free percent of memory into a memory pressure value. |
+MemoryPressureObserverChromeOS::MemoryPressureLevel |
+GetMemoryPressureLevelFromFillLevel( |
+ int memory_fill_level) { |
+ if (memory_fill_level < 50) |
+ return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_LOW; |
+ if (memory_fill_level < 75) |
+ return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_MODERATE; |
+ if (memory_fill_level < 90) |
+ return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_HIGH; |
+ return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_CRITICAL; |
+} |
+ |
+// Gets the used ChromeOS memory in percent. |
+int 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; |
+ |
+ DCHECK(available_memory < total_memory); |
+ int percentage = ((total_memory - available_memory) * 100) / total_memory; |
+ return percentage; |
+} |
+ |
+} // namespace |
+ |
+MemoryPressureObserverChromeOS::MemoryPressureObserverChromeOS() |
+ : current_memory_pressure_level_(MEMORY_PRESSURE_LEVEL_LOW) { |
+ StartObserving(); |
+} |
+ |
+MemoryPressureObserverChromeOS::~MemoryPressureObserverChromeOS() { |
+ StopObserving(); |
+} |
+ |
+void MemoryPressureObserverChromeOS::StartObserving() { |
+ timer_.Start(FROM_HERE, |
+ base::TimeDelta::FromMilliseconds(kMemoryPressureIntervalInMS), |
+ base::Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure, |
+ base::Unretained(this))); |
+} |
+ |
+void MemoryPressureObserverChromeOS::StopObserving() { |
+ // If StartObserving failed, StopObserving will still get called. |
+ timer_.Stop(); |
+} |
+ |
+void MemoryPressureObserverChromeOS::CheckMemoryPressure() { |
+ MemoryPressureLevel old_pressure = current_memory_pressure_level_; |
+ MemoryPressureLevel new_pressure = |
+ GetMemoryPressureLevelFromFillLevel(GetUsedMemoryInPercent()); |
+ if (old_pressure != new_pressure) { |
+ current_memory_pressure_level_ = new_pressure; |
+ switch (new_pressure) { |
+ case MEMORY_PRESSURE_LEVEL_LOW: |
+ // The |MemoryPressureListener| does currently not support this. |
+ break; |
+ case MEMORY_PRESSURE_LEVEL_MODERATE: |
+ MemoryPressureListener::NotifyMemoryPressure( |
+ MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); |
+ break; |
+ case MEMORY_PRESSURE_LEVEL_HIGH: |
+ // The |MemoryPressureListener| does currently not support this. |
+ break; |
+ case MEMORY_PRESSURE_LEVEL_CRITICAL: |
+ MemoryPressureListener::NotifyMemoryPressure( |
+ MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); |
+ break; |
+ } |
+ } |
+} |
+ |
+} // namespace base |