OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/chromeos/memory_pressure_monitor_chromeos.h" | 5 #include "base/chromeos/memory_pressure_monitor.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <sys/select.h> | 8 #include <sys/select.h> |
9 | 9 |
10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
11 #include "base/posix/eintr_wrapper.h" | 11 #include "base/posix/eintr_wrapper.h" |
12 #include "base/process/process_metrics.h" | 12 #include "base/process/process_metrics.h" |
13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
14 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
16 | 16 |
17 namespace base { | 17 namespace base { |
| 18 namespace chromeos { |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
21 // The time between memory pressure checks. While under critical pressure, this | 22 // The time between memory pressure checks. While under critical pressure, this |
22 // is also the timer to repeat cleanup attempts. | 23 // is also the timer to repeat cleanup attempts. |
23 const int kMemoryPressureIntervalMs = 1000; | 24 const int kMemoryPressureIntervalMs = 1000; |
24 | 25 |
25 // The time which should pass between two moderate memory pressure calls. | 26 // The time which should pass between two moderate memory pressure calls. |
26 const int kModerateMemoryPressureCooldownMs = 10000; | 27 const int kModerateMemoryPressureCooldownMs = 10000; |
27 | 28 |
(...skipping 18 matching lines...) Expand all Loading... |
46 }; | 47 }; |
47 | 48 |
48 // This is the file that will exist if low memory notification is available | 49 // This is the file that will exist if low memory notification is available |
49 // on the device. Whenever it becomes readable, it signals a low memory | 50 // on the device. Whenever it becomes readable, it signals a low memory |
50 // condition. | 51 // condition. |
51 const char kLowMemFile[] = "/dev/chromeos-low-mem"; | 52 const char kLowMemFile[] = "/dev/chromeos-low-mem"; |
52 | 53 |
53 // Converts a |MemoryPressureThreshold| value into a used memory percentage for | 54 // Converts a |MemoryPressureThreshold| value into a used memory percentage for |
54 // the moderate pressure event. | 55 // the moderate pressure event. |
55 int GetModerateMemoryThresholdInPercent( | 56 int GetModerateMemoryThresholdInPercent( |
56 MemoryPressureMonitorChromeOS::MemoryPressureThresholds thresholds) { | 57 MemoryPressureMonitor::MemoryPressureThresholds thresholds) { |
57 return thresholds == MemoryPressureMonitorChromeOS:: | 58 return thresholds == MemoryPressureMonitor:: |
58 THRESHOLD_AGGRESSIVE_CACHE_DISCARD || | 59 THRESHOLD_AGGRESSIVE_CACHE_DISCARD || |
59 thresholds == MemoryPressureMonitorChromeOS::THRESHOLD_AGGRESSIVE | 60 thresholds == MemoryPressureMonitor::THRESHOLD_AGGRESSIVE |
60 ? kAggressiveMemoryPressureModerateThresholdPercent | 61 ? kAggressiveMemoryPressureModerateThresholdPercent |
61 : kNormalMemoryPressureModerateThresholdPercent; | 62 : kNormalMemoryPressureModerateThresholdPercent; |
62 } | 63 } |
63 | 64 |
64 // Converts a |MemoryPressureThreshold| value into a used memory percentage for | 65 // Converts a |MemoryPressureThreshold| value into a used memory percentage for |
65 // the critical pressure event. | 66 // the critical pressure event. |
66 int GetCriticalMemoryThresholdInPercent( | 67 int GetCriticalMemoryThresholdInPercent( |
67 MemoryPressureMonitorChromeOS::MemoryPressureThresholds thresholds) { | 68 MemoryPressureMonitor::MemoryPressureThresholds thresholds) { |
68 return thresholds == MemoryPressureMonitorChromeOS:: | 69 return thresholds == MemoryPressureMonitor:: |
69 THRESHOLD_AGGRESSIVE_TAB_DISCARD || | 70 THRESHOLD_AGGRESSIVE_TAB_DISCARD || |
70 thresholds == MemoryPressureMonitorChromeOS::THRESHOLD_AGGRESSIVE | 71 thresholds == MemoryPressureMonitor::THRESHOLD_AGGRESSIVE |
71 ? kAggressiveMemoryPressureCriticalThresholdPercent | 72 ? kAggressiveMemoryPressureCriticalThresholdPercent |
72 : kNormalMemoryPressureCriticalThresholdPercent; | 73 : kNormalMemoryPressureCriticalThresholdPercent; |
73 } | 74 } |
74 | 75 |
75 // Converts free percent of memory into a memory pressure value. | 76 // Converts free percent of memory into a memory pressure value. |
76 MemoryPressureListener::MemoryPressureLevel GetMemoryPressureLevelFromFillLevel( | 77 MemoryPressureListener::MemoryPressureLevel GetMemoryPressureLevelFromFillLevel( |
77 int actual_fill_level, | 78 int actual_fill_level, |
78 int moderate_threshold, | 79 int moderate_threshold, |
79 int critical_threshold) { | 80 int critical_threshold) { |
80 if (actual_fill_level < moderate_threshold) | 81 if (actual_fill_level < moderate_threshold) |
(...skipping 13 matching lines...) Expand all Loading... |
94 FD_SET(file_descriptor, &fds); | 95 FD_SET(file_descriptor, &fds); |
95 | 96 |
96 tv.tv_sec = 0; | 97 tv.tv_sec = 0; |
97 tv.tv_usec = 0; | 98 tv.tv_usec = 0; |
98 | 99 |
99 return HANDLE_EINTR(select(file_descriptor + 1, &fds, NULL, NULL, &tv)) > 0; | 100 return HANDLE_EINTR(select(file_descriptor + 1, &fds, NULL, NULL, &tv)) > 0; |
100 } | 101 } |
101 | 102 |
102 } // namespace | 103 } // namespace |
103 | 104 |
104 MemoryPressureMonitorChromeOS::MemoryPressureMonitorChromeOS( | 105 MemoryPressureMonitor::MemoryPressureMonitor( |
105 MemoryPressureThresholds thresholds) | 106 MemoryPressureThresholds thresholds) |
106 : current_memory_pressure_level_( | 107 : current_memory_pressure_level_( |
107 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), | 108 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), |
108 moderate_pressure_repeat_count_(0), | 109 moderate_pressure_repeat_count_(0), |
109 moderate_pressure_threshold_percent_( | 110 moderate_pressure_threshold_percent_( |
110 GetModerateMemoryThresholdInPercent(thresholds)), | 111 GetModerateMemoryThresholdInPercent(thresholds)), |
111 critical_pressure_threshold_percent_( | 112 critical_pressure_threshold_percent_( |
112 GetCriticalMemoryThresholdInPercent(thresholds)), | 113 GetCriticalMemoryThresholdInPercent(thresholds)), |
113 low_mem_file_(HANDLE_EINTR(::open(kLowMemFile, O_RDONLY))), | 114 low_mem_file_(HANDLE_EINTR(::open(kLowMemFile, O_RDONLY))), |
114 weak_ptr_factory_(this) { | 115 weak_ptr_factory_(this) { |
115 StartObserving(); | 116 StartObserving(); |
116 LOG_IF(ERROR, !low_mem_file_.is_valid()) << "Cannot open kernel listener"; | 117 LOG_IF(ERROR, !low_mem_file_.is_valid()) << "Cannot open kernel listener"; |
117 } | 118 } |
118 | 119 |
119 MemoryPressureMonitorChromeOS::~MemoryPressureMonitorChromeOS() { | 120 MemoryPressureMonitor::~MemoryPressureMonitor() { |
120 StopObserving(); | 121 StopObserving(); |
121 } | 122 } |
122 | 123 |
123 void MemoryPressureMonitorChromeOS::ScheduleEarlyCheck() { | 124 void MemoryPressureMonitor::ScheduleEarlyCheck() { |
124 ThreadTaskRunnerHandle::Get()->PostTask( | 125 ThreadTaskRunnerHandle::Get()->PostTask( |
125 FROM_HERE, Bind(&MemoryPressureMonitorChromeOS::CheckMemoryPressure, | 126 FROM_HERE, Bind(&MemoryPressureMonitor::CheckMemoryPressure, |
126 weak_ptr_factory_.GetWeakPtr())); | 127 weak_ptr_factory_.GetWeakPtr())); |
127 } | 128 } |
128 | 129 |
129 MemoryPressureListener::MemoryPressureLevel | 130 MemoryPressureListener::MemoryPressureLevel |
130 MemoryPressureMonitorChromeOS::GetCurrentPressureLevel() const { | 131 MemoryPressureMonitor::GetCurrentPressureLevel() const { |
131 return current_memory_pressure_level_; | 132 return current_memory_pressure_level_; |
132 } | 133 } |
133 | 134 |
134 void MemoryPressureMonitorChromeOS::StartObserving() { | 135 // static |
| 136 MemoryPressureMonitor* MemoryPressureMonitor::Get() { |
| 137 return static_cast<MemoryPressureMonitor*>( |
| 138 base::MemoryPressureMonitor::Get()); |
| 139 } |
| 140 |
| 141 void MemoryPressureMonitor::StartObserving() { |
135 timer_.Start(FROM_HERE, | 142 timer_.Start(FROM_HERE, |
136 TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs), | 143 TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs), |
137 Bind(&MemoryPressureMonitorChromeOS:: | 144 Bind(&MemoryPressureMonitor:: |
138 CheckMemoryPressureAndRecordStatistics, | 145 CheckMemoryPressureAndRecordStatistics, |
139 weak_ptr_factory_.GetWeakPtr())); | 146 weak_ptr_factory_.GetWeakPtr())); |
140 } | 147 } |
141 | 148 |
142 void MemoryPressureMonitorChromeOS::StopObserving() { | 149 void MemoryPressureMonitor::StopObserving() { |
143 // If StartObserving failed, StopObserving will still get called. | 150 // If StartObserving failed, StopObserving will still get called. |
144 timer_.Stop(); | 151 timer_.Stop(); |
145 } | 152 } |
146 | 153 |
147 void MemoryPressureMonitorChromeOS::CheckMemoryPressureAndRecordStatistics() { | 154 void MemoryPressureMonitor::CheckMemoryPressureAndRecordStatistics() { |
148 CheckMemoryPressure(); | 155 CheckMemoryPressure(); |
149 | 156 |
150 // Record UMA histogram statistics for the current memory pressure level. | 157 // Record UMA histogram statistics for the current memory pressure level. |
151 MemoryPressureLevelUMA memory_pressure_level_uma(MEMORY_PRESSURE_LEVEL_NONE); | 158 MemoryPressureLevelUMA memory_pressure_level_uma(MEMORY_PRESSURE_LEVEL_NONE); |
152 switch (current_memory_pressure_level_) { | 159 switch (current_memory_pressure_level_) { |
153 case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: | 160 case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: |
154 memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_NONE; | 161 memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_NONE; |
155 break; | 162 break; |
156 case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: | 163 case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: |
157 memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_MODERATE; | 164 memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_MODERATE; |
158 break; | 165 break; |
159 case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: | 166 case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: |
160 memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_CRITICAL; | 167 memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_CRITICAL; |
161 break; | 168 break; |
162 } | 169 } |
163 | 170 |
164 UMA_HISTOGRAM_ENUMERATION("ChromeOS.MemoryPressureLevel", | 171 UMA_HISTOGRAM_ENUMERATION("ChromeOS.MemoryPressureLevel", |
165 memory_pressure_level_uma, | 172 memory_pressure_level_uma, |
166 NUM_MEMORY_PRESSURE_LEVELS); | 173 NUM_MEMORY_PRESSURE_LEVELS); |
167 } | 174 } |
168 | 175 |
169 void MemoryPressureMonitorChromeOS::CheckMemoryPressure() { | 176 void MemoryPressureMonitor::CheckMemoryPressure() { |
170 MemoryPressureListener::MemoryPressureLevel old_pressure = | 177 MemoryPressureListener::MemoryPressureLevel old_pressure = |
171 current_memory_pressure_level_; | 178 current_memory_pressure_level_; |
172 | 179 |
173 // If we have the kernel low memory observer, we use it's flag instead of our | 180 // If we have the kernel low memory observer, we use it's flag instead of our |
174 // own computation (for now). Note that in "simulation mode" it can be null. | 181 // own computation (for now). Note that in "simulation mode" it can be null. |
175 // TODO(skuhne): We need to add code which makes sure that the kernel and this | 182 // TODO(skuhne): We need to add code which makes sure that the kernel and this |
176 // computation come to similar results and then remove this override again. | 183 // computation come to similar results and then remove this override again. |
177 // TODO(skuhne): Add some testing framework here to see how close the kernel | 184 // TODO(skuhne): Add some testing framework here to see how close the kernel |
178 // and the internal functions are. | 185 // and the internal functions are. |
179 if (low_mem_file_.is_valid() && IsLowMemoryCondition(low_mem_file_.get())) { | 186 if (low_mem_file_.is_valid() && IsLowMemoryCondition(low_mem_file_.get())) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 // When we reducing the pressure level from critical to moderate, we | 224 // When we reducing the pressure level from critical to moderate, we |
218 // restart the timeout and do not send another notification. | 225 // restart the timeout and do not send another notification. |
219 moderate_pressure_repeat_count_ = 0; | 226 moderate_pressure_repeat_count_ = 0; |
220 return; | 227 return; |
221 } | 228 } |
222 moderate_pressure_repeat_count_ = 0; | 229 moderate_pressure_repeat_count_ = 0; |
223 MemoryPressureListener::NotifyMemoryPressure(current_memory_pressure_level_); | 230 MemoryPressureListener::NotifyMemoryPressure(current_memory_pressure_level_); |
224 } | 231 } |
225 | 232 |
226 // Gets the used ChromeOS memory in percent. | 233 // Gets the used ChromeOS memory in percent. |
227 int MemoryPressureMonitorChromeOS::GetUsedMemoryInPercent() { | 234 int MemoryPressureMonitor::GetUsedMemoryInPercent() { |
228 base::SystemMemoryInfoKB info; | 235 base::SystemMemoryInfoKB info; |
229 if (!base::GetSystemMemoryInfo(&info)) { | 236 if (!base::GetSystemMemoryInfo(&info)) { |
230 VLOG(1) << "Cannot determine the free memory of the system."; | 237 VLOG(1) << "Cannot determine the free memory of the system."; |
231 return 0; | 238 return 0; |
232 } | 239 } |
233 // TODO(skuhne): Instead of adding the kernel memory pressure calculation | 240 // TODO(skuhne): Instead of adding the kernel memory pressure calculation |
234 // logic here, we should have a kernel mechanism similar to the low memory | 241 // logic here, we should have a kernel mechanism similar to the low memory |
235 // notifier in ChromeOS which offers multiple pressure states. | 242 // notifier in ChromeOS which offers multiple pressure states. |
236 // To track this, we have crbug.com/381196. | 243 // To track this, we have crbug.com/381196. |
237 | 244 |
(...skipping 16 matching lines...) Expand all Loading... |
254 | 261 |
255 // Available memory is the sum of free, swap and easy reclaimable memory. | 262 // Available memory is the sum of free, swap and easy reclaimable memory. |
256 int available_memory = | 263 int available_memory = |
257 info.free + info.swap_free / kSwapWeight + file_memory; | 264 info.free + info.swap_free / kSwapWeight + file_memory; |
258 | 265 |
259 DCHECK(available_memory < total_memory); | 266 DCHECK(available_memory < total_memory); |
260 int percentage = ((total_memory - available_memory) * 100) / total_memory; | 267 int percentage = ((total_memory - available_memory) * 100) / total_memory; |
261 return percentage; | 268 return percentage; |
262 } | 269 } |
263 | 270 |
| 271 } // namespace chromeos |
264 } // namespace base | 272 } // namespace base |
OLD | NEW |