OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 // Histogram is an object that aggregates statistics, and can summarize them in | 5 // Histogram is an object that aggregates statistics, and can summarize them in |
6 // various forms, including ASCII graphical, HTML, and numerically (as a | 6 // various forms, including ASCII graphical, HTML, and numerically (as a |
7 // vector of numbers corresponding to each of the aggregating buckets). | 7 // vector of numbers corresponding to each of the aggregating buckets). |
8 | 8 |
9 // It supports calls to accumulate either time intervals (which are processed | 9 // It supports calls to accumulate either time intervals (which are processed |
10 // as integral number of milliseconds), or arbitrary integral units. | 10 // as integral number of milliseconds), or arbitrary integral units. |
(...skipping 26 matching lines...) Expand all Loading... |
37 | 37 |
38 #include "base/lock.h" | 38 #include "base/lock.h" |
39 #include "base/ref_counted.h" | 39 #include "base/ref_counted.h" |
40 #include "base/logging.h" | 40 #include "base/logging.h" |
41 #include "base/time.h" | 41 #include "base/time.h" |
42 | 42 |
43 //------------------------------------------------------------------------------ | 43 //------------------------------------------------------------------------------ |
44 // Provide easy general purpose histogram in a macro, just like stats counters. | 44 // Provide easy general purpose histogram in a macro, just like stats counters. |
45 // The first four macros use 50 buckets. | 45 // The first four macros use 50 buckets. |
46 | 46 |
47 #define HISTOGRAM_TIMES(name, sample) do { \ | 47 #define HISTOGRAM_TIMES(name, sample) HISTOGRAM_CUSTOM_TIMES( \ |
48 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | 48 name, sample, base::TimeDelta::FromMilliseconds(1), \ |
49 (name), base::TimeDelta::FromMilliseconds(1), \ | 49 base::TimeDelta::FromSeconds(10), 50) |
50 base::TimeDelta::FromSeconds(10), 50); \ | |
51 counter->AddTime(sample); \ | |
52 } while (0) | |
53 | 50 |
54 #define HISTOGRAM_COUNTS(name, sample) do { \ | 51 #define HISTOGRAM_COUNTS(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ |
55 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | 52 name, sample, 1, 1000000, 50) |
56 (name), 1, 1000000, 50); \ | 53 |
| 54 #define HISTOGRAM_COUNTS_100(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ |
| 55 name, sample, 1, 100, 50) |
| 56 |
| 57 #define HISTOGRAM_COUNTS_10000(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ |
| 58 name, sample, 1, 10000, 50) |
| 59 |
| 60 #define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ |
| 61 static scoped_refptr<Histogram> counter = Histogram::FactoryGet( \ |
| 62 name, min, max, bucket_count, Histogram::kNoFlags); \ |
57 counter->Add(sample); \ | 63 counter->Add(sample); \ |
58 } while (0) | 64 } while (0) |
59 | 65 |
60 #define HISTOGRAM_COUNTS_100(name, sample) do { \ | 66 #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ |
61 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | 67 HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) |
62 (name), 1, 100, 50); \ | |
63 counter->Add(sample); \ | |
64 } while (0) | |
65 | |
66 #define HISTOGRAM_COUNTS_10000(name, sample) do { \ | |
67 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | |
68 (name), 1, 10000, 50); \ | |
69 counter->Add(sample); \ | |
70 } while (0) | |
71 | |
72 #define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ | |
73 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | |
74 (name), min, max, bucket_count); \ | |
75 counter->Add(sample); \ | |
76 } while (0) | |
77 | |
78 #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) do { \ | |
79 static scoped_refptr<Histogram> counter = \ | |
80 LinearHistogram::LinearHistogramFactoryGet(\ | |
81 (name), 1, 100, 101); \ | |
82 counter->Add(under_one_hundred); \ | |
83 } while (0) | |
84 | 68 |
85 // For folks that need real specific times, use this to select a precise range | 69 // For folks that need real specific times, use this to select a precise range |
86 // of times you want plotted, and the number of buckets you want used. | 70 // of times you want plotted, and the number of buckets you want used. |
87 #define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ | 71 #define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ |
88 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | 72 static scoped_refptr<Histogram> counter = Histogram::FactoryGet( \ |
89 (name), min, max, bucket_count); \ | 73 name, min, max, bucket_count, Histogram::kNoFlags); \ |
90 counter->AddTime(sample); \ | 74 counter->AddTime(sample); \ |
91 } while (0) | 75 } while (0) |
92 | 76 |
93 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. | 77 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. |
94 #define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ | 78 #define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ |
95 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | 79 static scoped_refptr<Histogram> counter = Histogram::FactoryGet( \ |
96 (name), min, max, bucket_count); \ | 80 name, min, max, bucket_count, Histogram::kNoFlags); \ |
97 if ((sample) < (max)) counter->AddTime(sample); \ | 81 if ((sample) < (max)) counter->AddTime(sample); \ |
98 } while (0) | 82 } while (0) |
99 | 83 |
100 //------------------------------------------------------------------------------ | 84 // Support histograming of an enumerated value. The samples should always be |
101 // This macro set is for a histogram that can support both addition and removal | 85 // less than boundary_value. |
102 // of samples. It should be used to render the accumulated asset allocation | |
103 // of some samples. For example, it can sample memory allocation sizes, and | |
104 // memory releases (as negative samples). | |
105 // To simplify the interface, only non-zero values can be sampled, with positive | |
106 // numbers indicating addition, and negative numbers implying dimunition | |
107 // (removal). | |
108 // Note that the underlying ThreadSafeHistogram() uses locking to ensure that | |
109 // counts are precise (no chance of losing an addition or removal event, due to | |
110 // multithread racing). This precision is required to prevent missed-counts from | |
111 // resulting in drift, as the calls to Remove() for a given value should always | |
112 // be equal in number or fewer than the corresponding calls to Add(). | |
113 | 86 |
114 #define ASSET_HISTOGRAM_COUNTS(name, sample) do { \ | 87 #define HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \ |
115 static scoped_refptr<Histogram> counter = \ | 88 static scoped_refptr<Histogram> counter = LinearHistogram::FactoryGet( \ |
116 ThreadSafeHistogram::ThreadSafeHistogramFactoryGet(\ | 89 name, 1, boundary_value, boundary_value + 1, Histogram::kNoFlags); \ |
117 (name), 1, 1000000, 50); \ | 90 counter->Add(sample); \ |
118 if (0 == sample) break; \ | |
119 if (sample >= 0) \ | |
120 counter->Add(sample); \ | |
121 else\ | |
122 counter->Remove(-sample); \ | |
123 } while (0) | 91 } while (0) |
124 | 92 |
| 93 |
125 //------------------------------------------------------------------------------ | 94 //------------------------------------------------------------------------------ |
126 // Define Debug vs non-debug flavors of macros. | 95 // Define Debug vs non-debug flavors of macros. |
127 #ifndef NDEBUG | 96 #ifndef NDEBUG |
128 | 97 |
129 #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample) | 98 #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample) |
130 #define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample) | 99 #define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample) |
131 #define DASSET_HISTOGRAM_COUNTS(name, sample) ASSET_HISTOGRAM_COUNTS(name, \ | |
132 sample) | |
133 #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) HISTOGRAM_PERCENTAGE(\ | 100 #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) HISTOGRAM_PERCENTAGE(\ |
134 name, under_one_hundred) | 101 name, under_one_hundred) |
135 #define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \ | 102 #define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \ |
136 HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) | 103 HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) |
137 #define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \ | 104 #define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \ |
138 HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) | 105 HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) |
139 #define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \ | 106 #define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \ |
140 HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) | 107 HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) |
| 108 #define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) \ |
| 109 HISTOGRAM_ENUMERATION(name, sample, boundary_value) |
141 | 110 |
142 #else // NDEBUG | 111 #else // NDEBUG |
143 | 112 |
144 #define DHISTOGRAM_TIMES(name, sample) do {} while (0) | 113 #define DHISTOGRAM_TIMES(name, sample) do {} while (0) |
145 #define DHISTOGRAM_COUNTS(name, sample) do {} while (0) | 114 #define DHISTOGRAM_COUNTS(name, sample) do {} while (0) |
146 #define DASSET_HISTOGRAM_COUNTS(name, sample) do {} while (0) | |
147 #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) do {} while (0) | 115 #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) do {} while (0) |
148 #define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \ | 116 #define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \ |
149 do {} while (0) | 117 do {} while (0) |
150 #define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \ | 118 #define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \ |
151 do {} while (0) | 119 do {} while (0) |
152 #define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \ | 120 #define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \ |
153 do {} while (0) | 121 do {} while (0) |
154 | 122 #define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) do {} while (0) |
155 | 123 |
156 #endif // NDEBUG | 124 #endif // NDEBUG |
157 | 125 |
158 //------------------------------------------------------------------------------ | 126 //------------------------------------------------------------------------------ |
159 // The following macros provide typical usage scenarios for callers that wish | 127 // The following macros provide typical usage scenarios for callers that wish |
160 // to record histogram data, and have the data submitted/uploaded via UMA. | 128 // to record histogram data, and have the data submitted/uploaded via UMA. |
161 // Not all systems support such UMA, but if they do, the following macros | 129 // Not all systems support such UMA, but if they do, the following macros |
162 // should work with the service. | 130 // should work with the service. |
163 | 131 |
164 static const int kUmaTargetedHistogramFlag = 0x1; | 132 #define UMA_HISTOGRAM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ |
| 133 name, sample, base::TimeDelta::FromMilliseconds(1), \ |
| 134 base::TimeDelta::FromSeconds(10), 50) |
165 | 135 |
166 // This indicates the histogram is pickled to be sent across an IPC Channel. | 136 #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ |
167 // If we observe this flag during unpickle method, then we are running in a | 137 name, sample, base::TimeDelta::FromMilliseconds(10), \ |
168 // single process mode. | 138 base::TimeDelta::FromMinutes(3), 50) |
169 static const int kIPCSerializationSourceFlag = 1 << 4; | |
170 | 139 |
171 // Some histograms aren't currently destroyed. Until such users properly | 140 // Use this macro when times can routinely be much longer than 10 seconds. |
172 // decref those histograms, we will mark there histograms as planned to leak so | 141 #define UMA_HISTOGRAM_LONG_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ |
173 // that we can catch any user that directly tries to call delete "directly" | 142 name, sample, base::TimeDelta::FromMilliseconds(1), \ |
174 // rather than using the reference counting features that should take care of | 143 base::TimeDelta::FromHours(1), 50) |
175 // this. | |
176 // TODO(jar): Make this flag unnecessary! | |
177 static const int kPlannedLeakFlag = 1 << 5; | |
178 | 144 |
179 #define UMA_HISTOGRAM_TIMES(name, sample) do { \ | 145 #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ |
180 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | 146 static scoped_refptr<Histogram> counter = Histogram::FactoryGet( \ |
181 (name), base::TimeDelta::FromMilliseconds(1), \ | 147 name, min, max, bucket_count, Histogram::kUmaTargetedHistogramFlag); \ |
182 base::TimeDelta::FromSeconds(10), 50); \ | |
183 counter->SetFlags(kUmaTargetedHistogramFlag); \ | |
184 counter->AddTime(sample); \ | 148 counter->AddTime(sample); \ |
185 } while (0) | 149 } while (0) |
186 | 150 |
187 #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) do { \ | 151 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. |
188 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | |
189 (name), base::TimeDelta::FromMilliseconds(10), \ | |
190 base::TimeDelta::FromMinutes(3), 50); \ | |
191 counter->SetFlags(kUmaTargetedHistogramFlag); \ | |
192 counter->AddTime(sample); \ | |
193 } while (0) | |
194 | |
195 // Use this macro when times can routinely be much longer than 10 seconds. | |
196 #define UMA_HISTOGRAM_LONG_TIMES(name, sample) do { \ | |
197 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | |
198 (name), base::TimeDelta::FromMilliseconds(1), \ | |
199 base::TimeDelta::FromHours(1), 50); \ | |
200 counter->SetFlags(kUmaTargetedHistogramFlag); \ | |
201 counter->AddTime(sample); \ | |
202 } while (0) | |
203 | |
204 #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ | |
205 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | |
206 (name), min, max, bucket_count); \ | |
207 counter->SetFlags(kUmaTargetedHistogramFlag); \ | |
208 counter->AddTime(sample); \ | |
209 } while (0) | |
210 | |
211 #define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ | 152 #define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ |
212 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | 153 static scoped_refptr<Histogram> counter = Histogram::FactoryGet( \ |
213 (name), min, max, bucket_count); \ | 154 name, min, max, bucket_count, Histogram::kUmaTargetedHistogramFlag); \ |
214 counter->SetFlags(kUmaTargetedHistogramFlag); \ | |
215 if ((sample) < (max)) counter->AddTime(sample); \ | 155 if ((sample) < (max)) counter->AddTime(sample); \ |
216 } while (0) | 156 } while (0) |
217 | 157 |
218 #define UMA_HISTOGRAM_COUNTS(name, sample) do { \ | 158 #define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
219 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | 159 name, sample, 1, 1000000, 50) |
220 (name), 1, 1000000, 50); \ | 160 |
221 counter->SetFlags(kUmaTargetedHistogramFlag); \ | 161 #define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 162 name, sample, 1, 100, 50) |
| 163 |
| 164 #define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 165 name, sample, 1, 10000, 50) |
| 166 |
| 167 #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ |
| 168 static scoped_refptr<Histogram> counter = Histogram::FactoryGet( \ |
| 169 name, min, max, bucket_count, Histogram::kUmaTargetedHistogramFlag); \ |
222 counter->Add(sample); \ | 170 counter->Add(sample); \ |
223 } while (0) | 171 } while (0) |
224 | 172 |
225 #define UMA_HISTOGRAM_COUNTS_100(name, sample) do { \ | 173 #define UMA_HISTOGRAM_MEMORY_KB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
226 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | 174 name, sample, 1000, 500000, 50) |
227 (name), 1, 100, 50); \ | 175 |
228 counter->SetFlags(kUmaTargetedHistogramFlag); \ | 176 #define UMA_HISTOGRAM_MEMORY_MB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 177 name, sample, 1, 1000, 50) |
| 178 |
| 179 #define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ |
| 180 UMA_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) |
| 181 |
| 182 #define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \ |
| 183 DCHECK(sample < boundary_value); \ |
| 184 static scoped_refptr<Histogram> counter = LinearHistogram::FactoryGet( \ |
| 185 name, 1, boundary_value, boundary_value + 1, \ |
| 186 Histogram::kUmaTargetedHistogramFlag); \ |
229 counter->Add(sample); \ | 187 counter->Add(sample); \ |
230 } while (0) | 188 } while (0) |
231 | 189 |
232 #define UMA_HISTOGRAM_COUNTS_10000(name, sample) do { \ | |
233 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | |
234 (name), 1, 10000, 50); \ | |
235 counter->SetFlags(kUmaTargetedHistogramFlag); \ | |
236 counter->Add(sample); \ | |
237 } while (0) | |
238 | |
239 #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ | |
240 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | |
241 (name), min, max, bucket_count); \ | |
242 counter->SetFlags(kUmaTargetedHistogramFlag); \ | |
243 counter->Add(sample); \ | |
244 } while (0) | |
245 | |
246 #define UMA_HISTOGRAM_MEMORY_KB(name, sample) do { \ | |
247 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | |
248 (name), 1000, 500000, 50); \ | |
249 counter->SetFlags(kUmaTargetedHistogramFlag); \ | |
250 counter->Add(sample); \ | |
251 } while (0) | |
252 | |
253 #define UMA_HISTOGRAM_MEMORY_MB(name, sample) do { \ | |
254 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\ | |
255 (name), 1, 1000, 50); \ | |
256 counter->SetFlags(kUmaTargetedHistogramFlag); \ | |
257 counter->Add(sample); \ | |
258 } while (0) | |
259 | |
260 #define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) do { \ | |
261 static scoped_refptr<Histogram> counter = \ | |
262 LinearHistogram::LinearHistogramFactoryGet(\ | |
263 (name), 1, 100, 101); \ | |
264 counter->SetFlags(kUmaTargetedHistogramFlag); \ | |
265 counter->Add(under_one_hundred); \ | |
266 } while (0) | |
267 | 190 |
268 //------------------------------------------------------------------------------ | 191 //------------------------------------------------------------------------------ |
269 | 192 |
270 class Pickle; | 193 class Pickle; |
271 class Histogram; | 194 class Histogram; |
272 class LinearHistogram; | 195 class LinearHistogram; |
273 class BooleanHistogram; | 196 class BooleanHistogram; |
274 class ThreadSafeHistogram; | |
275 | 197 |
276 namespace disk_cache { | 198 namespace disk_cache { |
277 class StatsHistogram; | 199 class StatsHistogram; |
278 }; // namespace disk_cache | 200 }; // namespace disk_cache |
279 | 201 |
280 | 202 |
281 class Histogram : public base::RefCountedThreadSafe<Histogram> { | 203 class Histogram : public base::RefCountedThreadSafe<Histogram> { |
282 public: | 204 public: |
283 typedef int Sample; // Used for samples (and ranges of samples). | 205 typedef int Sample; // Used for samples (and ranges of samples). |
284 typedef int Count; // Used to count samples in a bucket. | 206 typedef int Count; // Used to count samples in a bucket. |
285 static const Sample kSampleType_MAX = INT_MAX; | 207 static const Sample kSampleType_MAX = INT_MAX; |
286 | 208 |
287 typedef std::vector<Count> Counts; | 209 typedef std::vector<Count> Counts; |
288 typedef std::vector<Sample> Ranges; | 210 typedef std::vector<Sample> Ranges; |
289 | 211 |
290 static const int kHexRangePrintingFlag; | |
291 | |
292 /* These enums are meant to facilitate deserialization of renderer histograms | 212 /* These enums are meant to facilitate deserialization of renderer histograms |
293 into the browser. */ | 213 into the browser. */ |
294 enum ClassType { | 214 enum ClassType { |
295 HISTOGRAM, | 215 HISTOGRAM, |
296 LINEAR_HISTOGRAM, | 216 LINEAR_HISTOGRAM, |
297 BOOLEAN_HISTOGRAM, | 217 BOOLEAN_HISTOGRAM, |
298 THREAD_SAFE_HISTOGRAM, | |
299 NOT_VALID_IN_RENDERER | 218 NOT_VALID_IN_RENDERER |
300 }; | 219 }; |
301 | 220 |
302 enum BucketLayout { | 221 enum BucketLayout { |
303 EXPONENTIAL, | 222 EXPONENTIAL, |
304 LINEAR | 223 LINEAR |
305 }; | 224 }; |
306 | 225 |
| 226 enum Flags { |
| 227 kNoFlags = 0, |
| 228 kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded. |
| 229 |
| 230 // Indicate that the histogram was pickled to be sent across an IPC Channel. |
| 231 // If we observe this flag on a histogram being aggregated into after IPC, |
| 232 // then we are running in a single process mode, and the aggregation should |
| 233 // not take place (as we would be aggregating back into the source |
| 234 // histogram!). |
| 235 kIPCSerializationSourceFlag = 0x10, |
| 236 |
| 237 kHexRangePrintingFlag = 0x8000, // Fancy bucket-naming supported. |
| 238 }; |
| 239 |
307 struct DescriptionPair { | 240 struct DescriptionPair { |
308 Sample sample; | 241 Sample sample; |
309 const char* description; // Null means end of a list of pairs. | 242 const char* description; // Null means end of a list of pairs. |
310 }; | 243 }; |
311 | 244 |
312 //---------------------------------------------------------------------------- | 245 //---------------------------------------------------------------------------- |
313 // Statistic values, developed over the life of the histogram. | 246 // Statistic values, developed over the life of the histogram. |
314 | 247 |
315 class SampleSet { | 248 class SampleSet { |
316 public: | 249 public: |
(...skipping 24 matching lines...) Expand all Loading... |
341 Counts counts_; | 274 Counts counts_; |
342 | 275 |
343 // Save simple stats locally. Note that this MIGHT get done in base class | 276 // Save simple stats locally. Note that this MIGHT get done in base class |
344 // without shared memory at some point. | 277 // without shared memory at some point. |
345 int64 sum_; // sum of samples. | 278 int64 sum_; // sum of samples. |
346 int64 square_sum_; // sum of squares of samples. | 279 int64 square_sum_; // sum of squares of samples. |
347 }; | 280 }; |
348 //---------------------------------------------------------------------------- | 281 //---------------------------------------------------------------------------- |
349 // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit | 282 // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit |
350 // default underflow bucket. | 283 // default underflow bucket. |
351 static scoped_refptr<Histogram> HistogramFactoryGet(const std::string& name, | 284 static scoped_refptr<Histogram> FactoryGet(const std::string& name, |
352 Sample minimum, Sample maximum, size_t bucket_count); | 285 Sample minimum, Sample maximum, size_t bucket_count, Flags flags); |
353 static scoped_refptr<Histogram> HistogramFactoryGet(const std::string& name, | 286 static scoped_refptr<Histogram> FactoryGet(const std::string& name, |
354 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count); | 287 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count, |
| 288 Flags flags); |
355 | 289 |
356 void Add(int value); | 290 void Add(int value); |
357 | 291 |
358 // This method is an interface, used only by BooleanHistogram. | 292 // This method is an interface, used only by BooleanHistogram. |
359 virtual void AddBoolean(bool value) { DCHECK(false); } | 293 virtual void AddBoolean(bool value) { DCHECK(false); } |
360 | 294 |
361 // Accept a TimeDelta to increment. | 295 // Accept a TimeDelta to increment. |
362 void AddTime(base::TimeDelta time) { | 296 void AddTime(base::TimeDelta time) { |
363 Add(static_cast<int>(time.InMilliseconds())); | 297 Add(static_cast<int>(time.InMilliseconds())); |
364 } | 298 } |
365 | 299 |
366 void AddSampleSet(const SampleSet& sample); | 300 void AddSampleSet(const SampleSet& sample); |
367 | 301 |
368 // This method is an interface, used only by ThreadSafeHistogram. | |
369 virtual void Remove(int value) { DCHECK(false); } | |
370 | |
371 // This method is an interface, used only by LinearHistogram. | 302 // This method is an interface, used only by LinearHistogram. |
372 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]) | 303 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]) |
373 { DCHECK(false); } | 304 { DCHECK(false); } |
374 | 305 |
375 // The following methods provide graphical histogram displays. | 306 // The following methods provide graphical histogram displays. |
376 void WriteHTMLGraph(std::string* output) const; | 307 void WriteHTMLGraph(std::string* output) const; |
377 void WriteAscii(bool graph_it, const std::string& newline, | 308 void WriteAscii(bool graph_it, const std::string& newline, |
378 std::string* output) const; | 309 std::string* output) const; |
379 | 310 |
380 // Support generic flagging of Histograms. | 311 // Support generic flagging of Histograms. |
381 // 0x1 Currently used to mark this histogram to be recorded by UMA.. | 312 // 0x1 Currently used to mark this histogram to be recorded by UMA.. |
382 // 0x8000 means print ranges in hex. | 313 // 0x8000 means print ranges in hex. |
383 void SetFlags(int flags) { flags_ |= flags; } | 314 void SetFlags(Flags flags) { flags_ = static_cast<Flags> (flags_ | flags); } |
384 void ClearFlags(int flags) { flags_ &= ~flags; } | 315 void ClearFlags(Flags flags) { flags_ = static_cast<Flags>(flags_ & ~flags); } |
385 int flags() const { return flags_; } | 316 int flags() const { return flags_; } |
386 | 317 |
387 // Convenience methods for serializing/deserializing the histograms. | 318 // Convenience methods for serializing/deserializing the histograms. |
388 // Histograms from Renderer process are serialized and sent to the browser. | 319 // Histograms from Renderer process are serialized and sent to the browser. |
389 // Browser process reconstructs the histogram from the pickled version | 320 // Browser process reconstructs the histogram from the pickled version |
390 // accumulates the browser-side shadow copy of histograms (that mirror | 321 // accumulates the browser-side shadow copy of histograms (that mirror |
391 // histograms created in the renderer). | 322 // histograms created in the renderer). |
392 | 323 |
393 // Serialize the given snapshot of a Histogram into a String. Uses | 324 // Serialize the given snapshot of a Histogram into a String. Uses |
394 // Pickle class to flatten the object. | 325 // Pickle class to flatten the object. |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 // named instances will be coalesced cross-project TODO(jar). | 434 // named instances will be coalesced cross-project TODO(jar). |
504 // If a user needs one histogram name to be called by several places in a | 435 // If a user needs one histogram name to be called by several places in a |
505 // single process, a central function should be defined by teh user, which | 436 // single process, a central function should be defined by teh user, which |
506 // defins the single declared instance of the named histogram. | 437 // defins the single declared instance of the named histogram. |
507 const std::string histogram_name_; | 438 const std::string histogram_name_; |
508 Sample declared_min_; // Less than this goes into counts_[0] | 439 Sample declared_min_; // Less than this goes into counts_[0] |
509 Sample declared_max_; // Over this goes into counts_[bucket_count_ - 1]. | 440 Sample declared_max_; // Over this goes into counts_[bucket_count_ - 1]. |
510 size_t bucket_count_; // Dimension of counts_[]. | 441 size_t bucket_count_; // Dimension of counts_[]. |
511 | 442 |
512 // Flag the histogram for recording by UMA via metric_services.h. | 443 // Flag the histogram for recording by UMA via metric_services.h. |
513 int flags_; | 444 Flags flags_; |
514 | 445 |
515 // For each index, show the least value that can be stored in the | 446 // For each index, show the least value that can be stored in the |
516 // corresponding bucket. We also append one extra element in this array, | 447 // corresponding bucket. We also append one extra element in this array, |
517 // containing kSampleType_MAX, to make calculations easy. | 448 // containing kSampleType_MAX, to make calculations easy. |
518 // The dimension of ranges_ is bucket_count + 1. | 449 // The dimension of ranges_ is bucket_count + 1. |
519 Ranges ranges_; | 450 Ranges ranges_; |
520 | 451 |
521 // Finally, provide the state that changes with the addition of each new | 452 // Finally, provide the state that changes with the addition of each new |
522 // sample. | 453 // sample. |
523 SampleSet sample_; | 454 SampleSet sample_; |
524 | 455 |
525 DISALLOW_COPY_AND_ASSIGN(Histogram); | 456 DISALLOW_COPY_AND_ASSIGN(Histogram); |
526 }; | 457 }; |
527 | 458 |
528 //------------------------------------------------------------------------------ | 459 //------------------------------------------------------------------------------ |
529 | 460 |
530 // LinearHistogram is a more traditional histogram, with evenly spaced | 461 // LinearHistogram is a more traditional histogram, with evenly spaced |
531 // buckets. | 462 // buckets. |
532 class LinearHistogram : public Histogram { | 463 class LinearHistogram : public Histogram { |
533 public: | 464 public: |
534 virtual ClassType histogram_type() const { return LINEAR_HISTOGRAM; } | 465 virtual ClassType histogram_type() const { return LINEAR_HISTOGRAM; } |
535 | 466 |
536 // Store a list of number/text values for use in rendering the histogram. | 467 // Store a list of number/text values for use in rendering the histogram. |
537 // The last element in the array has a null in its "description" slot. | 468 // The last element in the array has a null in its "description" slot. |
538 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]); | 469 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]); |
539 | 470 |
540 /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit | 471 /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit |
541 default underflow bucket. */ | 472 default underflow bucket. */ |
542 static scoped_refptr<Histogram> LinearHistogramFactoryGet( | 473 static scoped_refptr<Histogram> FactoryGet(const std::string& name, |
543 const std::string& name, Sample minimum, Sample maximum, | 474 Sample minimum, Sample maximum, size_t bucket_count, Flags flags); |
544 size_t bucket_count); | 475 static scoped_refptr<Histogram> FactoryGet(const std::string& name, |
545 static scoped_refptr<Histogram> LinearHistogramFactoryGet( | 476 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count, |
546 const std::string& name, base::TimeDelta minimum, | 477 Flags flags); |
547 base::TimeDelta maximum, size_t bucket_count); | |
548 | 478 |
549 protected: | 479 protected: |
550 LinearHistogram(const std::string& name, Sample minimum, | 480 LinearHistogram(const std::string& name, Sample minimum, |
551 Sample maximum, size_t bucket_count); | 481 Sample maximum, size_t bucket_count); |
552 | 482 |
553 LinearHistogram(const std::string& name, base::TimeDelta minimum, | 483 LinearHistogram(const std::string& name, base::TimeDelta minimum, |
554 base::TimeDelta maximum, size_t bucket_count); | 484 base::TimeDelta maximum, size_t bucket_count); |
555 | 485 |
556 virtual ~LinearHistogram() {} | 486 virtual ~LinearHistogram() {} |
557 | 487 |
(...skipping 17 matching lines...) Expand all Loading... |
575 BucketDescriptionMap bucket_description_; | 505 BucketDescriptionMap bucket_description_; |
576 | 506 |
577 DISALLOW_COPY_AND_ASSIGN(LinearHistogram); | 507 DISALLOW_COPY_AND_ASSIGN(LinearHistogram); |
578 }; | 508 }; |
579 | 509 |
580 //------------------------------------------------------------------------------ | 510 //------------------------------------------------------------------------------ |
581 | 511 |
582 // BooleanHistogram is a histogram for booleans. | 512 // BooleanHistogram is a histogram for booleans. |
583 class BooleanHistogram : public LinearHistogram { | 513 class BooleanHistogram : public LinearHistogram { |
584 public: | 514 public: |
585 static scoped_refptr<Histogram> BooleanHistogramFactoryGet( | 515 static scoped_refptr<Histogram> FactoryGet(const std::string& name, |
586 const std::string& name); | 516 Flags flags); |
587 | 517 |
588 virtual ClassType histogram_type() const { return BOOLEAN_HISTOGRAM; } | 518 virtual ClassType histogram_type() const { return BOOLEAN_HISTOGRAM; } |
589 | 519 |
590 virtual void AddBoolean(bool value) { Add(value ? 1 : 0); } | 520 virtual void AddBoolean(bool value) { Add(value ? 1 : 0); } |
591 | 521 |
592 private: | 522 private: |
593 explicit BooleanHistogram(const std::string& name) | 523 explicit BooleanHistogram(const std::string& name) |
594 : LinearHistogram(name, 1, 2, 3) { | 524 : LinearHistogram(name, 1, 2, 3) { |
595 } | 525 } |
596 | 526 |
597 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram); | 527 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram); |
598 }; | 528 }; |
599 | 529 |
600 //------------------------------------------------------------------------------ | 530 //------------------------------------------------------------------------------ |
601 // This section provides implementation for ThreadSafeHistogram. | |
602 //------------------------------------------------------------------------------ | |
603 | |
604 class ThreadSafeHistogram : public Histogram { | |
605 public: | |
606 static scoped_refptr<Histogram> ThreadSafeHistogramFactoryGet( | |
607 const std::string& name, Sample minimum, Sample maximum, | |
608 size_t bucket_count); | |
609 | |
610 virtual ClassType histogram_type() const { return THREAD_SAFE_HISTOGRAM; } | |
611 | |
612 // Provide the analog to Add() | |
613 virtual void Remove(int value); | |
614 | |
615 protected: | |
616 ThreadSafeHistogram(const std::string& name, Sample minimum, | |
617 Sample maximum, size_t bucket_count); | |
618 | |
619 virtual ~ThreadSafeHistogram() {} | |
620 | |
621 // Provide locked versions to get precise counts. | |
622 virtual void Accumulate(Sample value, Count count, size_t index); | |
623 | |
624 virtual void SnapshotSample(SampleSet* sample) const; | |
625 | |
626 private: | |
627 mutable Lock lock_; | |
628 | |
629 DISALLOW_COPY_AND_ASSIGN(ThreadSafeHistogram); | |
630 }; | |
631 | |
632 //------------------------------------------------------------------------------ | |
633 // StatisticsRecorder handles all histograms in the system. It provides a | 531 // StatisticsRecorder handles all histograms in the system. It provides a |
634 // general place for histograms to register, and supports a global API for | 532 // general place for histograms to register, and supports a global API for |
635 // accessing (i.e., dumping, or graphing) the data in all the histograms. | 533 // accessing (i.e., dumping, or graphing) the data in all the histograms. |
636 | 534 |
637 class StatisticsRecorder { | 535 class StatisticsRecorder { |
638 public: | 536 public: |
639 typedef std::vector<scoped_refptr<Histogram> > Histograms; | 537 typedef std::vector<scoped_refptr<Histogram> > Histograms; |
640 | 538 |
641 StatisticsRecorder(); | 539 StatisticsRecorder(); |
642 | 540 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
686 // lock protects access to the above map. | 584 // lock protects access to the above map. |
687 static Lock* lock_; | 585 static Lock* lock_; |
688 | 586 |
689 // Dump all known histograms to log. | 587 // Dump all known histograms to log. |
690 static bool dump_on_exit_; | 588 static bool dump_on_exit_; |
691 | 589 |
692 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); | 590 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); |
693 }; | 591 }; |
694 | 592 |
695 #endif // BASE_HISTOGRAM_H_ | 593 #endif // BASE_HISTOGRAM_H_ |
OLD | NEW |