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

Side by Side Diff: base/memory/memory_pressure_monitor_chromeos.cc

Issue 2783613002: WIP: memory coordinator: Check /dev/chromeos-low-mem to determine memory condition
Patch Set: Created 3 years, 8 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 unified diff | Download patch
OLDNEW
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/memory/memory_pressure_monitor_chromeos.h" 5 #include "base/memory/memory_pressure_monitor_chromeos.h"
6 6
7 #include <fcntl.h> 7 #include "base/memory/ptr_util.h"
8 #include <sys/select.h>
9
10 #include "base/metrics/histogram_macros.h" 8 #include "base/metrics/histogram_macros.h"
11 #include "base/posix/eintr_wrapper.h"
12 #include "base/process/process_metrics.h" 9 #include "base/process/process_metrics.h"
13 #include "base/single_thread_task_runner.h" 10 #include "base/single_thread_task_runner.h"
14 #include "base/sys_info.h"
15 #include "base/threading/thread_task_runner_handle.h" 11 #include "base/threading/thread_task_runner_handle.h"
16 #include "base/time/time.h" 12 #include "base/time/time.h"
17 13
18 namespace base { 14 namespace base {
19 namespace chromeos { 15 namespace chromeos {
20 16
21 namespace { 17 namespace {
22 18
23 // The time between memory pressure checks. While under critical pressure, this 19 // The time between memory pressure checks. While under critical pressure, this
24 // is also the timer to repeat cleanup attempts. 20 // is also the timer to repeat cleanup attempts.
(...skipping 15 matching lines...) Expand all
40 // The possible state for memory pressure level. The values should be in line 36 // The possible state for memory pressure level. The values should be in line
41 // with values in MemoryPressureListener::MemoryPressureLevel and should be 37 // with values in MemoryPressureListener::MemoryPressureLevel and should be
42 // updated if more memory pressure levels are introduced. 38 // updated if more memory pressure levels are introduced.
43 enum MemoryPressureLevelUMA { 39 enum MemoryPressureLevelUMA {
44 MEMORY_PRESSURE_LEVEL_NONE = 0, 40 MEMORY_PRESSURE_LEVEL_NONE = 0,
45 MEMORY_PRESSURE_LEVEL_MODERATE, 41 MEMORY_PRESSURE_LEVEL_MODERATE,
46 MEMORY_PRESSURE_LEVEL_CRITICAL, 42 MEMORY_PRESSURE_LEVEL_CRITICAL,
47 NUM_MEMORY_PRESSURE_LEVELS 43 NUM_MEMORY_PRESSURE_LEVELS
48 }; 44 };
49 45
50 // This is the file that will exist if low memory notification is available
51 // on the device. Whenever it becomes readable, it signals a low memory
52 // condition.
53 const char kLowMemFile[] = "/dev/chromeos-low-mem";
54
55 // Converts a |MemoryPressureThreshold| value into a used memory percentage for 46 // Converts a |MemoryPressureThreshold| value into a used memory percentage for
56 // the moderate pressure event. 47 // the moderate pressure event.
57 int GetModerateMemoryThresholdInPercent( 48 int GetModerateMemoryThresholdInPercent(
58 MemoryPressureMonitor::MemoryPressureThresholds thresholds) { 49 MemoryPressureMonitor::MemoryPressureThresholds thresholds) {
59 return thresholds == MemoryPressureMonitor:: 50 return thresholds == MemoryPressureMonitor::
60 THRESHOLD_AGGRESSIVE_CACHE_DISCARD || 51 THRESHOLD_AGGRESSIVE_CACHE_DISCARD ||
61 thresholds == MemoryPressureMonitor::THRESHOLD_AGGRESSIVE 52 thresholds == MemoryPressureMonitor::THRESHOLD_AGGRESSIVE
62 ? kAggressiveMemoryPressureModerateThresholdPercent 53 ? kAggressiveMemoryPressureModerateThresholdPercent
63 : kNormalMemoryPressureModerateThresholdPercent; 54 : kNormalMemoryPressureModerateThresholdPercent;
64 } 55 }
(...skipping 14 matching lines...) Expand all
79 int actual_fill_level, 70 int actual_fill_level,
80 int moderate_threshold, 71 int moderate_threshold,
81 int critical_threshold) { 72 int critical_threshold) {
82 if (actual_fill_level < moderate_threshold) 73 if (actual_fill_level < moderate_threshold)
83 return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; 74 return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
84 return actual_fill_level < critical_threshold 75 return actual_fill_level < critical_threshold
85 ? MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE 76 ? MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE
86 : MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; 77 : MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
87 } 78 }
88 79
89 // This function will be called less than once a second. It will check if
90 // the kernel has detected a low memory situation.
91 bool IsLowMemoryCondition(int file_descriptor) {
92 fd_set fds;
93 struct timeval tv;
94
95 FD_ZERO(&fds);
96 FD_SET(file_descriptor, &fds);
97
98 tv.tv_sec = 0;
99 tv.tv_usec = 0;
100
101 return HANDLE_EINTR(select(file_descriptor + 1, &fds, NULL, NULL, &tv)) > 0;
102 }
103
104 } // namespace 80 } // namespace
105 81
106 MemoryPressureMonitor::MemoryPressureMonitor( 82 MemoryPressureMonitor::MemoryPressureMonitor(
107 MemoryPressureThresholds thresholds) 83 MemoryPressureThresholds thresholds)
108 : current_memory_pressure_level_( 84 : current_memory_pressure_level_(
109 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), 85 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE),
110 moderate_pressure_repeat_count_(0), 86 moderate_pressure_repeat_count_(0),
111 seconds_since_reporting_(0), 87 seconds_since_reporting_(0),
112 moderate_pressure_threshold_percent_( 88 moderate_pressure_threshold_percent_(
113 GetModerateMemoryThresholdInPercent(thresholds)), 89 GetModerateMemoryThresholdInPercent(thresholds)),
114 critical_pressure_threshold_percent_( 90 critical_pressure_threshold_percent_(
115 GetCriticalMemoryThresholdInPercent(thresholds)), 91 GetCriticalMemoryThresholdInPercent(thresholds)),
116 low_mem_file_(HANDLE_EINTR(::open(kLowMemFile, O_RDONLY))), 92 low_mem_observer_(base::MakeUnique<LowMemoryObserver>()),
117 dispatch_callback_( 93 dispatch_callback_(
118 base::Bind(&MemoryPressureListener::NotifyMemoryPressure)), 94 base::Bind(&MemoryPressureListener::NotifyMemoryPressure)),
119 weak_ptr_factory_(this) { 95 weak_ptr_factory_(this) {
120 StartObserving(); 96 StartObserving();
121 LOG_IF(ERROR,
122 base::SysInfo::IsRunningOnChromeOS() && !low_mem_file_.is_valid())
123 << "Cannot open kernel listener";
124 } 97 }
125 98
126 MemoryPressureMonitor::~MemoryPressureMonitor() { 99 MemoryPressureMonitor::~MemoryPressureMonitor() {
127 StopObserving(); 100 StopObserving();
128 } 101 }
129 102
130 void MemoryPressureMonitor::ScheduleEarlyCheck() { 103 void MemoryPressureMonitor::ScheduleEarlyCheck() {
131 ThreadTaskRunnerHandle::Get()->PostTask( 104 ThreadTaskRunnerHandle::Get()->PostTask(
132 FROM_HERE, Bind(&MemoryPressureMonitor::CheckMemoryPressure, 105 FROM_HERE, Bind(&MemoryPressureMonitor::CheckMemoryPressure,
133 weak_ptr_factory_.GetWeakPtr())); 106 weak_ptr_factory_.GetWeakPtr()));
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 void MemoryPressureMonitor::CheckMemoryPressure() { 160 void MemoryPressureMonitor::CheckMemoryPressure() {
188 MemoryPressureListener::MemoryPressureLevel old_pressure = 161 MemoryPressureListener::MemoryPressureLevel old_pressure =
189 current_memory_pressure_level_; 162 current_memory_pressure_level_;
190 163
191 // If we have the kernel low memory observer, we use it's flag instead of our 164 // If we have the kernel low memory observer, we use it's flag instead of our
192 // own computation (for now). Note that in "simulation mode" it can be null. 165 // own computation (for now). Note that in "simulation mode" it can be null.
193 // TODO(skuhne): We need to add code which makes sure that the kernel and this 166 // TODO(skuhne): We need to add code which makes sure that the kernel and this
194 // computation come to similar results and then remove this override again. 167 // computation come to similar results and then remove this override again.
195 // TODO(skuhne): Add some testing framework here to see how close the kernel 168 // TODO(skuhne): Add some testing framework here to see how close the kernel
196 // and the internal functions are. 169 // and the internal functions are.
197 if (low_mem_file_.is_valid() && IsLowMemoryCondition(low_mem_file_.get())) { 170 if (low_mem_observer_->IsLowMemoryCondition()) {
198 current_memory_pressure_level_ = 171 current_memory_pressure_level_ =
199 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; 172 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
200 } else { 173 } else {
201 current_memory_pressure_level_ = GetMemoryPressureLevelFromFillLevel( 174 current_memory_pressure_level_ = GetMemoryPressureLevelFromFillLevel(
202 GetUsedMemoryInPercent(), 175 GetUsedMemoryInPercent(),
203 moderate_pressure_threshold_percent_, 176 moderate_pressure_threshold_percent_,
204 critical_pressure_threshold_percent_); 177 critical_pressure_threshold_percent_);
205 178
206 // When listening to the kernel, we ignore the reported memory pressure 179 // When listening to the kernel, we ignore the reported memory pressure
207 // level from our own computation and reduce critical to moderate. 180 // level from our own computation and reduce critical to moderate.
208 if (low_mem_file_.is_valid() && 181 if (low_mem_observer_->is_valid() &&
209 current_memory_pressure_level_ == 182 current_memory_pressure_level_ ==
210 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { 183 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
211 current_memory_pressure_level_ = 184 current_memory_pressure_level_ =
212 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; 185 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE;
213 } 186 }
214 } 187 }
215 188
216 // In case there is no memory pressure we do not notify. 189 // In case there is no memory pressure we do not notify.
217 if (current_memory_pressure_level_ == 190 if (current_memory_pressure_level_ ==
218 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) { 191 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
219 return; 192 return;
220 } 193 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 return percentage; 252 return percentage;
280 } 253 }
281 254
282 void MemoryPressureMonitor::SetDispatchCallback( 255 void MemoryPressureMonitor::SetDispatchCallback(
283 const DispatchCallback& callback) { 256 const DispatchCallback& callback) {
284 dispatch_callback_ = callback; 257 dispatch_callback_ = callback;
285 } 258 }
286 259
287 } // namespace chromeos 260 } // namespace chromeos
288 } // namespace base 261 } // namespace base
OLDNEW
« no previous file with comments | « base/memory/memory_pressure_monitor_chromeos.h ('k') | content/browser/memory/memory_condition_observer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698