OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/chromeos/memory_pressure_observer_chromeos.h" |
| 6 |
| 7 #include "base/process/process_metrics.h" |
| 8 #include "base/time/time.h" |
| 9 |
| 10 namespace base { |
| 11 |
| 12 namespace { |
| 13 |
| 14 // The time between memory pressure checks. |
| 15 const int kMemoryPressureIntervalInMS = 1000; |
| 16 |
| 17 // Converts free percent of memory into a memory pressure value. |
| 18 MemoryPressureObserverChromeOS::MemoryPressureLevel |
| 19 GetMemoryPressureLevelFromFillLevel( |
| 20 int memory_fill_level) { |
| 21 if (memory_fill_level < 50) |
| 22 return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_LOW; |
| 23 if (memory_fill_level < 75) |
| 24 return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_MODERATE; |
| 25 if (memory_fill_level < 90) |
| 26 return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_HIGH; |
| 27 return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_CRITICAL; |
| 28 } |
| 29 |
| 30 // Gets the used ChromeOS memory in percent. |
| 31 int GetUsedMemoryInPercent() { |
| 32 base::SystemMemoryInfoKB info; |
| 33 if (!base::GetSystemMemoryInfo(&info)) { |
| 34 VLOG(1) << "Cannot determine the free memory of the system."; |
| 35 return 0; |
| 36 } |
| 37 // TODO(skuhne): Instead of adding the kernel memory pressure calculation |
| 38 // logic here, we should have a kernel mechanism similar to the low memory |
| 39 // notifier in ChromeOS which offers multiple pressure states. |
| 40 // To track this, we have crbug.com/381196. |
| 41 |
| 42 // The available memory consists of "real" and virtual (z)ram memory. |
| 43 // Since swappable memory uses a non pre-deterministic compression and |
| 44 // the compression creates its own "dynamic" in the system, it gets |
| 45 // de-emphasized by the |kSwapWeight| factor. |
| 46 const int kSwapWeight = 4; |
| 47 |
| 48 // The total memory we have is the "real memory" plus the virtual (z)ram. |
| 49 int total_memory = info.total + info.swap_total / kSwapWeight; |
| 50 |
| 51 // The kernel internally uses 50MB. |
| 52 const int kMinFileMemory = 50 * 1024; |
| 53 |
| 54 // Most file memory can be easily reclaimed. |
| 55 int file_memory = info.active_file + info.inactive_file; |
| 56 // unless it is dirty or it's a minimal portion which is required. |
| 57 file_memory -= info.dirty + kMinFileMemory; |
| 58 |
| 59 // Available memory is the sum of free, swap and easy reclaimable memory. |
| 60 int available_memory = |
| 61 info.free + info.swap_free / kSwapWeight + file_memory; |
| 62 |
| 63 DCHECK(available_memory < total_memory); |
| 64 int percentage = ((total_memory - available_memory) * 100) / total_memory; |
| 65 return percentage; |
| 66 } |
| 67 |
| 68 } // namespace |
| 69 |
| 70 MemoryPressureObserverChromeOS::MemoryPressureObserverChromeOS() |
| 71 : current_memory_pressure_level_(MEMORY_PRESSURE_LEVEL_LOW) { |
| 72 StartObserving(); |
| 73 } |
| 74 |
| 75 MemoryPressureObserverChromeOS::~MemoryPressureObserverChromeOS() { |
| 76 StopObserving(); |
| 77 } |
| 78 |
| 79 void MemoryPressureObserverChromeOS::StartObserving() { |
| 80 timer_.Start(FROM_HERE, |
| 81 base::TimeDelta::FromMilliseconds(kMemoryPressureIntervalInMS), |
| 82 base::Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure, |
| 83 base::Unretained(this))); |
| 84 } |
| 85 |
| 86 void MemoryPressureObserverChromeOS::StopObserving() { |
| 87 // If StartObserving failed, StopObserving will still get called. |
| 88 timer_.Stop(); |
| 89 } |
| 90 |
| 91 void MemoryPressureObserverChromeOS::CheckMemoryPressure() { |
| 92 MemoryPressureLevel old_pressure = current_memory_pressure_level_; |
| 93 MemoryPressureLevel new_pressure = |
| 94 GetMemoryPressureLevelFromFillLevel(GetUsedMemoryInPercent()); |
| 95 if (old_pressure != new_pressure) { |
| 96 current_memory_pressure_level_ = new_pressure; |
| 97 switch (new_pressure) { |
| 98 case MEMORY_PRESSURE_LEVEL_LOW: |
| 99 // The |MemoryPressureListener| does currently not support this. |
| 100 break; |
| 101 case MEMORY_PRESSURE_LEVEL_MODERATE: |
| 102 MemoryPressureListener::NotifyMemoryPressure( |
| 103 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); |
| 104 break; |
| 105 case MEMORY_PRESSURE_LEVEL_HIGH: |
| 106 // The |MemoryPressureListener| does currently not support this. |
| 107 break; |
| 108 case MEMORY_PRESSURE_LEVEL_CRITICAL: |
| 109 MemoryPressureListener::NotifyMemoryPressure( |
| 110 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); |
| 111 break; |
| 112 } |
| 113 } |
| 114 } |
| 115 |
| 116 } // namespace base |
OLD | NEW |