OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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 "components/memory_pressure/memory_pressure_stats_collector.h" | |
6 | |
7 #include "base/metrics/histogram.h" | |
8 | |
9 namespace memory_pressure { | |
10 | |
11 namespace { | |
12 | |
13 using MemoryPressureLevel = MemoryPressureListener::MemoryPressureLevel; | |
14 | |
15 // A special memory pressure level that is used to indicate that the stats | |
16 // collector has not yet been called. | |
17 const MemoryPressureLevel MEMORY_PRESSURE_LEVEL_INVALID = | |
18 static_cast<MemoryPressureLevel>( | |
19 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE - 1); | |
20 | |
21 // Converts a memory pressure level to an UMA enumeration value. | |
22 MemoryPressureLevelUMA MemoryPressureLevelToUmaEnumValue( | |
23 MemoryPressureLevel level) { | |
24 switch (level) { | |
25 case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: | |
26 return UMA_MEMORY_PRESSURE_LEVEL_NONE; | |
27 case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: | |
28 return UMA_MEMORY_PRESSURE_LEVEL_MODERATE; | |
29 case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: | |
30 return UMA_MEMORY_PRESSURE_LEVEL_CRITICAL; | |
31 } | |
32 NOTREACHED(); | |
33 return UMA_MEMORY_PRESSURE_LEVEL_COUNT; | |
grt (UTC plus 2)
2015/09/08 17:22:46
this will lead to an out-of-bounds write on line 7
chrisha
2015/09/08 18:48:42
This is just to keep the compiler happy (MSVS PGO
| |
34 } | |
35 | |
36 // Converts an UMA enumeration value to a memory pressure level. | |
37 MemoryPressureLevel MemoryPressureLevelFromUmaEnumValue( | |
38 MemoryPressureLevelUMA level) { | |
39 switch (level) { | |
40 case UMA_MEMORY_PRESSURE_LEVEL_NONE: | |
41 return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; | |
42 case UMA_MEMORY_PRESSURE_LEVEL_MODERATE: | |
43 return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; | |
44 case UMA_MEMORY_PRESSURE_LEVEL_CRITICAL: | |
45 return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; | |
46 } | |
grt (UTC plus 2)
2015/09/08 17:22:46
case UMA_MEMORY_PRESSURE_LEVEL_COUNT:
NOTREA
chrisha
2015/09/08 18:48:43
Done.
| |
47 NOTREACHED(); | |
48 return MEMORY_PRESSURE_LEVEL_INVALID; | |
grt (UTC plus 2)
2015/09/08 17:22:46
returning something that isn't a real MemoryPressu
chrisha
2015/09/08 18:48:42
Same comment as above. It will never actually run,
| |
49 } | |
50 | |
51 } // namespace | |
52 | |
53 MemoryPressureStatsCollector::MemoryPressureStatsCollector( | |
54 base::TickClock* tick_clock) | |
55 : tick_clock_(tick_clock), | |
56 last_pressure_level_(MEMORY_PRESSURE_LEVEL_INVALID) {} | |
57 | |
58 void MemoryPressureStatsCollector::UpdateStatistics( | |
59 MemoryPressureLevel current_pressure_level) { | |
60 base::TimeTicks now = tick_clock_->NowTicks(); | |
61 | |
62 // Special case: first call to the collector. Observations have just started | |
63 // so there's nothing to report. | |
64 if (last_pressure_level_ == MEMORY_PRESSURE_LEVEL_INVALID) { | |
grt (UTC plus 2)
2015/09/08 17:22:46
can you do away with the MEMORY_PRESSURE_LEVEL_INV
chrisha
2015/09/08 18:48:43
sgtm. Done.
| |
65 last_pressure_level_ = current_pressure_level; | |
66 last_update_time_ = now; | |
67 return; | |
68 } | |
69 | |
70 // If the pressure level has transitioned then report this. | |
71 if (last_pressure_level_ != current_pressure_level) | |
72 ReportLevelChange(last_pressure_level_, current_pressure_level); | |
73 | |
74 // Increment the appropriate cumulative bucket. | |
75 int index = MemoryPressureLevelToUmaEnumValue(current_pressure_level); | |
76 base::TimeDelta time_since_update = now - last_update_time_; | |
grt (UTC plus 2)
2015/09/08 17:22:46
nit: inline the delta computation on the line belo
chrisha
2015/09/08 18:48:43
Done.
| |
77 unreported_cumulative_time_[index] += time_since_update; | |
78 | |
79 // Update last pressure related state. | |
80 last_pressure_level_ = current_pressure_level; | |
81 last_update_time_ = now; | |
82 | |
83 // Make reports about the amount of time spent cumulatively at each level. | |
84 for (size_t i = 0; i < arraysize(unreported_cumulative_time_); ++i) { | |
85 // Report the largest number of whole seconds possible at this moment and | |
86 // carry around the rest for a future report. | |
87 if (unreported_cumulative_time_[i].is_zero()) | |
88 continue; | |
89 int64_t seconds = unreported_cumulative_time_[i].InSeconds(); | |
90 if (seconds == 0) | |
91 continue; | |
92 unreported_cumulative_time_[i] -= base::TimeDelta::FromSeconds(seconds); | |
93 | |
94 ReportCumulativeTime(MemoryPressureLevelFromUmaEnumValue( | |
95 static_cast<MemoryPressureLevelUMA>(i)), | |
96 static_cast<int>(seconds)); | |
97 } | |
98 } | |
99 | |
100 namespace { | |
101 | |
102 // Converts a pressure state change to an UMA enumeration value. | |
grt (UTC plus 2)
2015/09/08 17:22:46
optional nit: move this into the unnamed namespace
chrisha
2015/09/08 18:48:43
I tend to prefer having private implementation det
| |
103 MemoryPressureLevelChangeUMA MemoryPressureLevelChangeToUmaEnumValue( | |
104 MemoryPressureLevel old_level, | |
105 MemoryPressureLevel new_level) { | |
106 switch (old_level) { | |
107 case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: { | |
108 if (new_level == MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE) | |
109 return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_NONE_TO_MODERATE; | |
110 if (new_level == MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) | |
grt (UTC plus 2)
2015/09/08 17:22:46
each of these will silently fall through if a new
chrisha
2015/09/08 18:48:43
I've gone with the break, as this is a case of "sh
| |
111 return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_NONE_TO_CRITICAL; | |
112 } | |
113 case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: { | |
114 if (new_level == MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) | |
115 return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_MODERATE_TO_NONE; | |
116 if (new_level == MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) | |
117 return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_MODERATE_TO_CRITICAL; | |
118 } | |
119 case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: { | |
120 if (new_level == MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) | |
121 return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_CRITICAL_TO_MODERATE; | |
122 if (new_level == MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE) | |
123 return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_CRITICAL_TO_MODERATE; | |
124 } | |
125 } | |
grt (UTC plus 2)
2015/09/08 17:22:46
add a case for UMA_MEMORY_PRESSURE_LEVEL_COUNT tha
chrisha
2015/09/08 18:48:43
This switches off the MemoryPressureListern enum,
grt (UTC plus 2)
2015/09/08 19:22:10
oh yeah, duh.
chrisha
2015/09/08 19:57:53
Acknowledged.
| |
126 NOTREACHED(); | |
127 return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_COUNT; | |
128 } | |
129 | |
130 } // namespace | |
131 | |
132 // static | |
133 void MemoryPressureStatsCollector::ReportCumulativeTime( | |
134 MemoryPressureLevel pressure_level, | |
135 int seconds) { | |
136 // Use the more primitive STATIC_HISTOGRAM_POINTER_BLOCK macro because the | |
137 // simple UMA_HISTOGRAM macros don't expose 'AddCount' functionality. | |
138 STATIC_HISTOGRAM_POINTER_BLOCK( | |
139 "Memory.PressureLevel", | |
140 AddCount(MemoryPressureLevelToUmaEnumValue(pressure_level), seconds), | |
141 base::LinearHistogram::FactoryGet( | |
142 "Memory.PressureLevel", 1, UMA_MEMORY_PRESSURE_LEVEL_COUNT, | |
143 UMA_MEMORY_PRESSURE_LEVEL_COUNT + 1, | |
144 base::HistogramBase::kUmaTargetedHistogramFlag)); | |
145 } | |
146 | |
147 // static | |
148 void MemoryPressureStatsCollector::ReportLevelChange( | |
149 MemoryPressureLevel old_pressure_level, | |
150 MemoryPressureLevel new_pressure_level) { | |
151 UMA_HISTOGRAM_ENUMERATION("Memory.PressureLevelChange", | |
152 MemoryPressureLevelChangeToUmaEnumValue( | |
153 old_pressure_level, new_pressure_level), | |
154 UMA_MEMORY_PRESSURE_LEVEL_CHANGE_COUNT); | |
155 } | |
156 | |
157 } // namespace memory_pressure | |
OLD | NEW |