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

Side by Side Diff: base/chromeos/memory_pressure_observer_chromeos.cc

Issue 874483008: Add UMA stats to get the quality of service of memory pressure handling scheme in ChromeOS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address the code review comments. Created 5 years, 10 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/chromeos/memory_pressure_observer_chromeos.h" 5 #include "base/chromeos/memory_pressure_observer_chromeos.h"
6 6
7 #include "base/message_loop/message_loop.h" 7 #include "base/message_loop/message_loop.h"
8 #include "base/metrics/histogram_macros.h"
8 #include "base/process/process_metrics.h" 9 #include "base/process/process_metrics.h"
9 #include "base/time/time.h" 10 #include "base/time/time.h"
10 11
11 namespace base { 12 namespace base {
12 13
13 namespace { 14 namespace {
14 15
15 // The time between memory pressure checks. While under critical pressure, this 16 // The time between memory pressure checks. While under critical pressure, this
16 // is also the timer to repeat cleanup attempts. 17 // is also the timer to repeat cleanup attempts.
17 const int kMemoryPressureIntervalMs = 1000; 18 const int kMemoryPressureIntervalMs = 1000;
18 19
19 // The time which should pass between two moderate memory pressure calls. 20 // The time which should pass between two moderate memory pressure calls.
20 const int kModerateMemoryPressureCooldownMs = 10000; 21 const int kModerateMemoryPressureCooldownMs = 10000;
21 22
22 // Number of event polls before the next moderate pressure event can be sent. 23 // Number of event polls before the next moderate pressure event can be sent.
23 const int kModerateMemoryPressureCooldown = 24 const int kModerateMemoryPressureCooldown =
24 kModerateMemoryPressureCooldownMs / kMemoryPressureIntervalMs; 25 kModerateMemoryPressureCooldownMs / kMemoryPressureIntervalMs;
25 26
26 // Threshold constants to emit pressure events. 27 // Threshold constants to emit pressure events.
27 const int kNormalMemoryPressureModerateThresholdPercent = 60; 28 const int kNormalMemoryPressureModerateThresholdPercent = 60;
28 const int kNormalMemoryPressureCriticalThresholdPercent = 90; 29 const int kNormalMemoryPressureCriticalThresholdPercent = 90;
29 const int kAggressiveMemoryPressureModerateThresholdPercent = 35; 30 const int kAggressiveMemoryPressureModerateThresholdPercent = 35;
30 const int kAggressiveMemoryPressureCriticalThresholdPercent = 70; 31 const int kAggressiveMemoryPressureCriticalThresholdPercent = 70;
31 32
33 // The number used to magnify the fraction of time spent in non critical state.
34 const int kNonCriticalTimeFractionMagnification = 1000000;
35
32 // Converts a |MemoryPressureThreshold| value into a used memory percentage for 36 // Converts a |MemoryPressureThreshold| value into a used memory percentage for
33 // the moderate pressure event. 37 // the moderate pressure event.
34 int GetModerateMemoryThresholdInPercent( 38 int GetModerateMemoryThresholdInPercent(
35 MemoryPressureObserverChromeOS::MemoryPressureThresholds thresholds) { 39 MemoryPressureObserverChromeOS::MemoryPressureThresholds thresholds) {
36 return thresholds == MemoryPressureObserverChromeOS:: 40 return thresholds == MemoryPressureObserverChromeOS::
37 THRESHOLD_AGGRESSIVE_CACHE_DISCARD || 41 THRESHOLD_AGGRESSIVE_CACHE_DISCARD ||
38 thresholds == MemoryPressureObserverChromeOS::THRESHOLD_AGGRESSIVE 42 thresholds == MemoryPressureObserverChromeOS::THRESHOLD_AGGRESSIVE
39 ? kAggressiveMemoryPressureModerateThresholdPercent 43 ? kAggressiveMemoryPressureModerateThresholdPercent
40 : kNormalMemoryPressureModerateThresholdPercent; 44 : kNormalMemoryPressureModerateThresholdPercent;
41 } 45 }
42 46
43 // Converts a |MemoryPressureThreshold| value into a used memory percentage for 47 // Converts a |MemoryPressureThreshold| value into a used memory percentage for
44 // the critical pressure event. 48 // the critical pressure event.
45 int GetCriticalMemoryThresholdInPercent( 49 int GetCriticalMemoryThresholdInPercent(
46 MemoryPressureObserverChromeOS::MemoryPressureThresholds thresholds) { 50 MemoryPressureObserverChromeOS::MemoryPressureThresholds thresholds) {
47 return thresholds == MemoryPressureObserverChromeOS:: 51 return thresholds == MemoryPressureObserverChromeOS::
48 THRESHOLD_AGGRESSIVE_TAB_DISCARD || 52 THRESHOLD_AGGRESSIVE_TAB_DISCARD ||
49 thresholds == MemoryPressureObserverChromeOS::THRESHOLD_AGGRESSIVE 53 thresholds == MemoryPressureObserverChromeOS::THRESHOLD_AGGRESSIVE
50 ? kAggressiveMemoryPressureCriticalThresholdPercent 54 ? kAggressiveMemoryPressureCriticalThresholdPercent
51 : kNormalMemoryPressureCriticalThresholdPercent; 55 : kNormalMemoryPressureCriticalThresholdPercent;
52 } 56 }
53 57
58 // Computes the by kNonCriticalTimeFractionMagnification scaled fraction of time
59 // spent in non critical state vs. in critical + non critical state.
60 int GetNonCriticalTimeRatio(TimeDelta critical_delta,
61 TimeDelta non_critical_delta) {
62 return (kNonCriticalTimeFractionMagnification *
63 non_critical_delta.InMilliseconds()) /
64 ((non_critical_delta + critical_delta).InMilliseconds());
65 }
66
67 void RecordNonCriticalTimeRatio(int non_critical_fraction) {
68 UMA_HISTOGRAM_COUNTS("ChromeOS.MemoryPressureHandleQuality.NonCriticalRatio",
69 non_critical_fraction);
70 }
71
54 // Converts free percent of memory into a memory pressure value. 72 // Converts free percent of memory into a memory pressure value.
55 MemoryPressureListener::MemoryPressureLevel GetMemoryPressureLevelFromFillLevel( 73 MemoryPressureListener::MemoryPressureLevel GetMemoryPressureLevelFromFillLevel(
56 int actual_fill_level, 74 int actual_fill_level,
57 int moderate_threshold, 75 int moderate_threshold,
58 int critical_threshold) { 76 int critical_threshold) {
59 if (actual_fill_level < moderate_threshold) 77 if (actual_fill_level < moderate_threshold)
60 return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; 78 return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
61 return actual_fill_level < critical_threshold 79 return actual_fill_level < critical_threshold
62 ? MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE 80 ? MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE
63 : MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; 81 : MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
64 } 82 }
65 83
66 } // namespace 84 } // namespace
67 85
68 MemoryPressureObserverChromeOS::MemoryPressureObserverChromeOS( 86 MemoryPressureObserverChromeOS::MemoryPressureObserverChromeOS(
69 MemoryPressureThresholds thresholds) 87 MemoryPressureThresholds thresholds)
70 : current_memory_pressure_level_( 88 : current_memory_pressure_level_(
71 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), 89 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE),
72 moderate_pressure_repeat_count_(0), 90 moderate_pressure_repeat_count_(0),
73 moderate_pressure_threshold_percent_( 91 moderate_pressure_threshold_percent_(
74 GetModerateMemoryThresholdInPercent(thresholds)), 92 GetModerateMemoryThresholdInPercent(thresholds)),
75 critical_pressure_threshold_percent_( 93 critical_pressure_threshold_percent_(
76 GetCriticalMemoryThresholdInPercent(thresholds)), 94 GetCriticalMemoryThresholdInPercent(thresholds)),
95 non_critical_start_time_(TimeTicks::Now()),
96 critical_start_time_(TimeTicks::Now()),
77 weak_ptr_factory_(this) { 97 weak_ptr_factory_(this) {
78 StartObserving(); 98 StartObserving();
79 } 99 }
80 100
81 MemoryPressureObserverChromeOS::~MemoryPressureObserverChromeOS() { 101 MemoryPressureObserverChromeOS::~MemoryPressureObserverChromeOS() {
102 // Before shutting down send the quality of service statistics.
103 if (GetMemoryPressureLevelFromFillLevel(
104 GetUsedMemoryInPercent(), moderate_pressure_threshold_percent_,
105 critical_pressure_threshold_percent_) ==
106 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
107 int fraction = GetNonCriticalTimeRatio(
108 TimeTicks::Now() - critical_start_time_,
109 critical_start_time_ - non_critical_start_time_);
110 RecordNonCriticalTimeRatio(fraction);
111 } else {
112 RecordNonCriticalTimeRatio(kNonCriticalTimeFractionMagnification);
113 }
114
82 StopObserving(); 115 StopObserving();
83 } 116 }
84 117
85 void MemoryPressureObserverChromeOS::ScheduleEarlyCheck() { 118 void MemoryPressureObserverChromeOS::ScheduleEarlyCheck() {
86 MessageLoop::current()->PostTask( 119 MessageLoop::current()->PostTask(
87 FROM_HERE, 120 FROM_HERE,
88 Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure, 121 Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure,
89 weak_ptr_factory_.GetWeakPtr())); 122 weak_ptr_factory_.GetWeakPtr()));
90 } 123 }
91 124
92 void MemoryPressureObserverChromeOS::StartObserving() { 125 void MemoryPressureObserverChromeOS::StartObserving() {
93 timer_.Start(FROM_HERE, 126 timer_.Start(FROM_HERE,
94 TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs), 127 TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs),
95 Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure, 128 Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure,
96 weak_ptr_factory_.GetWeakPtr())); 129 weak_ptr_factory_.GetWeakPtr()));
97 } 130 }
98 131
99 void MemoryPressureObserverChromeOS::StopObserving() { 132 void MemoryPressureObserverChromeOS::StopObserving() {
100 // If StartObserving failed, StopObserving will still get called. 133 // If StartObserving failed, StopObserving will still get called.
101 timer_.Stop(); 134 timer_.Stop();
102 } 135 }
103 136
104 void MemoryPressureObserverChromeOS::CheckMemoryPressure() { 137 void MemoryPressureObserverChromeOS::CheckMemoryPressure() {
105 MemoryPressureListener::MemoryPressureLevel old_pressure = 138 MemoryPressureListener::MemoryPressureLevel old_pressure =
106 current_memory_pressure_level_; 139 current_memory_pressure_level_;
107 current_memory_pressure_level_ = 140 current_memory_pressure_level_ =
108 GetMemoryPressureLevelFromFillLevel(GetUsedMemoryInPercent(), 141 GetMemoryPressureLevelFromFillLevel(GetUsedMemoryInPercent(),
109 moderate_pressure_threshold_percent_, 142 moderate_pressure_threshold_percent_,
110 critical_pressure_threshold_percent_); 143 critical_pressure_threshold_percent_);
144
145 // Record the quality of service of memory pressure handling.
146 if (old_pressure != current_memory_pressure_level_) {
147 TimeTicks now = TimeTicks::Now();
148 if (old_pressure ==
149 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
150 // When leaving the critical memory pressure, we compute the fraction of
151 // time spent in the non critical vs. the critical state. A larger value
152 // indicates a better management scheme.
153 int fraction = GetNonCriticalTimeRatio(
154 now - critical_start_time_,
155 critical_start_time_ - non_critical_start_time_);
156 RecordNonCriticalTimeRatio(fraction);
157 non_critical_start_time_ = now;
158 } else if (current_memory_pressure_level_ ==
159 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
160 critical_start_time_ = now;
161 }
162 }
163
111 // In case there is no memory pressure we do not notify. 164 // In case there is no memory pressure we do not notify.
112 if (current_memory_pressure_level_ == 165 if (current_memory_pressure_level_ ==
113 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) { 166 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
114 return; 167 return;
115 } 168 }
116 if (old_pressure == current_memory_pressure_level_) { 169 if (old_pressure == current_memory_pressure_level_) {
117 // If the memory pressure is still at the same level, we notify again for a 170 // 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 171 // critical level. In case of a moderate level repeat however, we only send
119 // a notification after a certain time has passed. 172 // a notification after a certain time has passed.
120 if (current_memory_pressure_level_ == 173 if (current_memory_pressure_level_ ==
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 // Available memory is the sum of free, swap and easy reclaimable memory. 221 // Available memory is the sum of free, swap and easy reclaimable memory.
169 int available_memory = 222 int available_memory =
170 info.free + info.swap_free / kSwapWeight + file_memory; 223 info.free + info.swap_free / kSwapWeight + file_memory;
171 224
172 DCHECK(available_memory < total_memory); 225 DCHECK(available_memory < total_memory);
173 int percentage = ((total_memory - available_memory) * 100) / total_memory; 226 int percentage = ((total_memory - available_memory) * 100) / total_memory;
174 return percentage; 227 return percentage;
175 } 228 }
176 229
177 } // namespace base 230 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698