Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / base / chromeos / memory_pressure_observer_chromeos.cc
blob8112c761e5e713e747cb015d8226e62a754c87a8
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.
5 #include "base/chromeos/memory_pressure_observer_chromeos.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/process/process_metrics.h"
9 #include "base/time/time.h"
11 namespace base {
13 namespace {
15 // The time between memory pressure checks. While under critical pressure, this
16 // is also the timer to repeat cleanup attempts.
17 const int kMemoryPressureIntervalMs = 1000;
19 // The time which should pass between two moderate memory pressure calls.
20 const int kModerateMemoryPressureCooldownMs = 10000;
22 // Number of event polls before the next moderate pressure event can be sent.
23 const int kModerateMemoryPressureCooldown =
24 kModerateMemoryPressureCooldownMs / kMemoryPressureIntervalMs;
26 // Threshold constants to emit pressure events.
27 const int kNormalMemoryPressureModerateThresholdPercent = 60;
28 const int kNormalMemoryPressureCriticalThresholdPercent = 90;
29 const int kAggressiveMemoryPressureModerateThresholdPercent = 35;
30 const int kAggressiveMemoryPressureCriticalThresholdPercent = 70;
32 // Converts a |MemoryPressureThreshold| value into a used memory percentage for
33 // the moderate pressure event.
34 int GetModerateMemoryThresholdInPercent(
35 MemoryPressureObserverChromeOS::MemoryPressureThresholds thresholds) {
36 return thresholds == MemoryPressureObserverChromeOS::
37 THRESHOLD_AGGRESSIVE_CACHE_DISCARD ||
38 thresholds == MemoryPressureObserverChromeOS::THRESHOLD_AGGRESSIVE
39 ? kAggressiveMemoryPressureModerateThresholdPercent
40 : kNormalMemoryPressureModerateThresholdPercent;
43 // Converts a |MemoryPressureThreshold| value into a used memory percentage for
44 // the critical pressure event.
45 int GetCriticalMemoryThresholdInPercent(
46 MemoryPressureObserverChromeOS::MemoryPressureThresholds thresholds) {
47 return thresholds == MemoryPressureObserverChromeOS::
48 THRESHOLD_AGGRESSIVE_TAB_DISCARD ||
49 thresholds == MemoryPressureObserverChromeOS::THRESHOLD_AGGRESSIVE
50 ? kAggressiveMemoryPressureCriticalThresholdPercent
51 : kNormalMemoryPressureCriticalThresholdPercent;
54 // Converts free percent of memory into a memory pressure value.
55 MemoryPressureListener::MemoryPressureLevel GetMemoryPressureLevelFromFillLevel(
56 int actual_fill_level,
57 int moderate_threshold,
58 int critical_threshold) {
59 if (actual_fill_level < moderate_threshold)
60 return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
61 return actual_fill_level < critical_threshold
62 ? MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE
63 : MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
66 } // namespace
68 MemoryPressureObserverChromeOS::MemoryPressureObserverChromeOS(
69 MemoryPressureThresholds thresholds)
70 : current_memory_pressure_level_(
71 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE),
72 moderate_pressure_repeat_count_(0),
73 moderate_pressure_threshold_percent_(
74 GetModerateMemoryThresholdInPercent(thresholds)),
75 critical_pressure_threshold_percent_(
76 GetCriticalMemoryThresholdInPercent(thresholds)),
77 weak_ptr_factory_(this) {
78 StartObserving();
81 MemoryPressureObserverChromeOS::~MemoryPressureObserverChromeOS() {
82 StopObserving();
85 void MemoryPressureObserverChromeOS::ScheduleEarlyCheck() {
86 MessageLoop::current()->PostTask(
87 FROM_HERE,
88 Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure,
89 weak_ptr_factory_.GetWeakPtr()));
92 void MemoryPressureObserverChromeOS::StartObserving() {
93 timer_.Start(FROM_HERE,
94 TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs),
95 Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure,
96 weak_ptr_factory_.GetWeakPtr()));
99 void MemoryPressureObserverChromeOS::StopObserving() {
100 // If StartObserving failed, StopObserving will still get called.
101 timer_.Stop();
104 void MemoryPressureObserverChromeOS::CheckMemoryPressure() {
105 MemoryPressureListener::MemoryPressureLevel old_pressure =
106 current_memory_pressure_level_;
107 current_memory_pressure_level_ =
108 GetMemoryPressureLevelFromFillLevel(GetUsedMemoryInPercent(),
109 moderate_pressure_threshold_percent_,
110 critical_pressure_threshold_percent_);
111 // In case there is no memory pressure we do not notify.
112 if (current_memory_pressure_level_ ==
113 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
114 return;
116 if (old_pressure == current_memory_pressure_level_) {
117 // If the memory pressure is still at the same level, we notify again for a
118 // critical level. In case of a moderate level repeat however, we only send
119 // a notification after a certain time has passed.
120 if (current_memory_pressure_level_ ==
121 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE &&
122 ++moderate_pressure_repeat_count_ <
123 kModerateMemoryPressureCooldown) {
124 return;
126 } else if (current_memory_pressure_level_ ==
127 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE &&
128 old_pressure ==
129 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
130 // When we reducing the pressure level from critical to moderate, we
131 // restart the timeout and do not send another notification.
132 moderate_pressure_repeat_count_ = 0;
133 return;
135 moderate_pressure_repeat_count_ = 0;
136 MemoryPressureListener::NotifyMemoryPressure(current_memory_pressure_level_);
139 // Gets the used ChromeOS memory in percent.
140 int MemoryPressureObserverChromeOS::GetUsedMemoryInPercent() {
141 base::SystemMemoryInfoKB info;
142 if (!base::GetSystemMemoryInfo(&info)) {
143 VLOG(1) << "Cannot determine the free memory of the system.";
144 return 0;
146 // TODO(skuhne): Instead of adding the kernel memory pressure calculation
147 // logic here, we should have a kernel mechanism similar to the low memory
148 // notifier in ChromeOS which offers multiple pressure states.
149 // To track this, we have crbug.com/381196.
151 // The available memory consists of "real" and virtual (z)ram memory.
152 // Since swappable memory uses a non pre-deterministic compression and
153 // the compression creates its own "dynamic" in the system, it gets
154 // de-emphasized by the |kSwapWeight| factor.
155 const int kSwapWeight = 4;
157 // The total memory we have is the "real memory" plus the virtual (z)ram.
158 int total_memory = info.total + info.swap_total / kSwapWeight;
160 // The kernel internally uses 50MB.
161 const int kMinFileMemory = 50 * 1024;
163 // Most file memory can be easily reclaimed.
164 int file_memory = info.active_file + info.inactive_file;
165 // unless it is dirty or it's a minimal portion which is required.
166 file_memory -= info.dirty + kMinFileMemory;
168 // Available memory is the sum of free, swap and easy reclaimable memory.
169 int available_memory =
170 info.free + info.swap_free / kSwapWeight + file_memory;
172 DCHECK(available_memory < total_memory);
173 int percentage = ((total_memory - available_memory) * 100) / total_memory;
174 return percentage;
177 } // namespace base