OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 10 matching lines...) Expand all Loading... | |
21 // The above example has an exponential ratio of 2 (doubling the bucket width | 21 // The above example has an exponential ratio of 2 (doubling the bucket width |
22 // in each consecutive bucket. The Histogram class automatically calculates | 22 // in each consecutive bucket. The Histogram class automatically calculates |
23 // the smallest ratio that it can use to construct the number of buckets | 23 // the smallest ratio that it can use to construct the number of buckets |
24 // selected in the constructor. An another example, if you had 50 buckets, | 24 // selected in the constructor. An another example, if you had 50 buckets, |
25 // and millisecond time values from 1 to 10000, then the ratio between | 25 // and millisecond time values from 1 to 10000, then the ratio between |
26 // consecutive bucket widths will be approximately somewhere around the 50th | 26 // consecutive bucket widths will be approximately somewhere around the 50th |
27 // root of 10000. This approach provides very fine grain (narrow) buckets | 27 // root of 10000. This approach provides very fine grain (narrow) buckets |
28 // at the low end of the histogram scale, but allows the histogram to cover a | 28 // at the low end of the histogram scale, but allows the histogram to cover a |
29 // gigantic range with the addition of very few buckets. | 29 // gigantic range with the addition of very few buckets. |
30 | 30 |
31 // Histograms use a pattern involving a function static variable, that is a | |
32 // pointer to a histogram. This static is explicitly initialized on any thread | |
33 // that detects a uninitialized (NULL) pointer. The potentially racy | |
34 // initialization is not a problem as it is always set to point to the same | |
35 // value (i.e., the FactoryGet always returns the same value). FactoryGet | |
36 // is also completely thread safe, which results in a completely thread safe, | |
37 // and relatively fast, set of counters. To avoid races at shutdown, the static | |
38 // pointer is NOT deleted, and we leak the histograms at process termination. | |
rvargas (doing something else)
2011/04/01 19:20:52
Have you considered using LazyInstance<> instead?
jar (doing other things)
2011/04/01 21:50:27
As per discussion, one major point is that this co
willchan no longer on Chromium
2011/04/02 07:43:31
I think you misunderstand LazyInstance. Both LazyI
| |
39 | |
31 #ifndef BASE_METRICS_HISTOGRAM_H_ | 40 #ifndef BASE_METRICS_HISTOGRAM_H_ |
32 #define BASE_METRICS_HISTOGRAM_H_ | 41 #define BASE_METRICS_HISTOGRAM_H_ |
33 #pragma once | 42 #pragma once |
34 | 43 |
35 #include <map> | 44 #include <map> |
36 #include <string> | 45 #include <string> |
37 #include <vector> | 46 #include <vector> |
38 | 47 |
39 #include "base/base_api.h" | 48 #include "base/base_api.h" |
40 #include "base/gtest_prod_util.h" | 49 #include "base/gtest_prod_util.h" |
41 #include "base/logging.h" | 50 #include "base/logging.h" |
42 #include "base/memory/ref_counted.h" | |
43 #include "base/time.h" | 51 #include "base/time.h" |
44 | 52 |
45 class Pickle; | 53 class Pickle; |
46 | 54 |
47 namespace base { | 55 namespace base { |
48 | 56 |
49 class Lock; | 57 class Lock; |
50 | 58 |
51 //------------------------------------------------------------------------------ | 59 //------------------------------------------------------------------------------ |
52 // Provide easy general purpose histogram in a macro, just like stats counters. | 60 // Provide easy general purpose histogram in a macro, just like stats counters. |
53 // The first four macros use 50 buckets. | 61 // The first four macros use 50 buckets. |
54 | 62 |
55 #define HISTOGRAM_TIMES(name, sample) HISTOGRAM_CUSTOM_TIMES( \ | 63 #define HISTOGRAM_TIMES(name, sample) HISTOGRAM_CUSTOM_TIMES( \ |
56 name, sample, base::TimeDelta::FromMilliseconds(1), \ | 64 name, sample, base::TimeDelta::FromMilliseconds(1), \ |
57 base::TimeDelta::FromSeconds(10), 50) | 65 base::TimeDelta::FromSeconds(10), 50) |
58 | 66 |
59 #define HISTOGRAM_COUNTS(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ | 67 #define HISTOGRAM_COUNTS(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ |
60 name, sample, 1, 1000000, 50) | 68 name, sample, 1, 1000000, 50) |
61 | 69 |
62 #define HISTOGRAM_COUNTS_100(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ | 70 #define HISTOGRAM_COUNTS_100(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ |
63 name, sample, 1, 100, 50) | 71 name, sample, 1, 100, 50) |
64 | 72 |
65 #define HISTOGRAM_COUNTS_10000(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ | 73 #define HISTOGRAM_COUNTS_10000(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ |
66 name, sample, 1, 10000, 50) | 74 name, sample, 1, 10000, 50) |
67 | 75 |
68 #define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ | 76 #define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ |
69 scoped_refptr<base::Histogram> counter = \ | 77 static base::Histogram* counter(NULL); \ |
70 base::Histogram::FactoryGet(name, min, max, bucket_count, \ | 78 if (!counter) \ |
71 base::Histogram::kNoFlags); \ | 79 counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \ |
80 base::Histogram::kNoFlags); \ | |
72 DCHECK_EQ(name, counter->histogram_name()); \ | 81 DCHECK_EQ(name, counter->histogram_name()); \ |
73 if (counter.get()) counter->Add(sample); \ | 82 counter->Add(sample); \ |
74 } while (0) | 83 } while (0) |
75 | 84 |
76 #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ | 85 #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ |
77 HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) | 86 HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) |
78 | 87 |
79 // For folks that need real specific times, use this to select a precise range | 88 // For folks that need real specific times, use this to select a precise range |
80 // of times you want plotted, and the number of buckets you want used. | 89 // of times you want plotted, and the number of buckets you want used. |
81 #define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ | 90 #define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ |
82 scoped_refptr<base::Histogram> counter = \ | 91 static base::Histogram* counter(NULL); \ |
83 base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ | 92 if (!counter) \ |
84 base::Histogram::kNoFlags); \ | 93 counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ |
94 base::Histogram::kNoFlags); \ | |
85 DCHECK_EQ(name, counter->histogram_name()); \ | 95 DCHECK_EQ(name, counter->histogram_name()); \ |
86 if (counter.get()) counter->AddTime(sample); \ | 96 counter->AddTime(sample); \ |
87 } while (0) | 97 } while (0) |
88 | 98 |
89 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. | 99 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. .... |
ramant (doing other things)
2011/04/01 20:05:38
More than 80 characters. Did you want to delete th
jar (doing other things)
2011/04/01 21:50:27
Done.
| |
90 #define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ | 100 #define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ |
91 scoped_refptr<base::Histogram> counter = \ | 101 static base::Histogram* counter(NULL); \ |
92 base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ | 102 if (!counter) \ |
93 base::Histogram::kNoFlags); \ | 103 counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ |
104 base::Histogram::kNoFlags); \ | |
94 DCHECK_EQ(name, counter->histogram_name()); \ | 105 DCHECK_EQ(name, counter->histogram_name()); \ |
95 if ((sample) < (max) && counter.get()) counter->AddTime(sample); \ | 106 if ((sample) < (max)) counter->AddTime(sample); \ |
96 } while (0) | 107 } while (0) |
97 | 108 |
98 // Support histograming of an enumerated value. The samples should always be | 109 // Support histograming of an enumerated value. The samples should always be |
99 // less than boundary_value. | 110 // less than boundary_value. |
100 | 111 |
101 #define HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \ | 112 #define HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \ |
102 scoped_refptr<base::Histogram> counter = \ | 113 static base::Histogram* counter(NULL); \ |
103 base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ | 114 if (!counter) \ |
104 boundary_value + 1, \ | 115 counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ |
105 base::Histogram::kNoFlags); \ | 116 boundary_value + 1, base::Histogram::kNoFlags); \ |
106 DCHECK_EQ(name, counter->histogram_name()); \ | 117 DCHECK_EQ(name, counter->histogram_name()); \ |
107 if (counter.get()) counter->Add(sample); \ | 118 counter->Add(sample); \ |
108 } while (0) | 119 } while (0) |
109 | 120 |
110 #define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \ | 121 #define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \ |
111 scoped_refptr<base::Histogram> counter = \ | 122 static base::Histogram* counter(NULL); \ |
112 base::CustomHistogram::FactoryGet(name, custom_ranges, \ | 123 if (!counter) \ |
113 base::Histogram::kNoFlags); \ | 124 counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \ |
125 base::Histogram::kNoFlags); \ | |
114 DCHECK_EQ(name, counter->histogram_name()); \ | 126 DCHECK_EQ(name, counter->histogram_name()); \ |
115 if (counter.get()) counter->Add(sample); \ | 127 counter->Add(sample); \ |
116 } while (0) | 128 } while (0) |
117 | 129 |
118 | 130 |
119 //------------------------------------------------------------------------------ | 131 //------------------------------------------------------------------------------ |
120 // Define Debug vs non-debug flavors of macros. | 132 // Define Debug vs non-debug flavors of macros. |
121 #ifndef NDEBUG | 133 #ifndef NDEBUG |
122 | 134 |
123 #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample) | 135 #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample) |
124 #define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample) | 136 #define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample) |
125 #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) HISTOGRAM_PERCENTAGE(\ | 137 #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) HISTOGRAM_PERCENTAGE(\ |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
165 #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ | 177 #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ |
166 name, sample, base::TimeDelta::FromMilliseconds(10), \ | 178 name, sample, base::TimeDelta::FromMilliseconds(10), \ |
167 base::TimeDelta::FromMinutes(3), 50) | 179 base::TimeDelta::FromMinutes(3), 50) |
168 | 180 |
169 // Use this macro when times can routinely be much longer than 10 seconds. | 181 // Use this macro when times can routinely be much longer than 10 seconds. |
170 #define UMA_HISTOGRAM_LONG_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ | 182 #define UMA_HISTOGRAM_LONG_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ |
171 name, sample, base::TimeDelta::FromMilliseconds(1), \ | 183 name, sample, base::TimeDelta::FromMilliseconds(1), \ |
172 base::TimeDelta::FromHours(1), 50) | 184 base::TimeDelta::FromHours(1), 50) |
173 | 185 |
174 #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ | 186 #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ |
175 scoped_refptr<base::Histogram> counter = \ | 187 static base::Histogram* counter(NULL); \ |
176 base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ | 188 if (!counter) \ |
189 counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ | |
177 base::Histogram::kUmaTargetedHistogramFlag); \ | 190 base::Histogram::kUmaTargetedHistogramFlag); \ |
178 DCHECK_EQ(name, counter->histogram_name()); \ | 191 DCHECK_EQ(name, counter->histogram_name()); \ |
179 if (counter.get()) counter->AddTime(sample); \ | 192 counter->AddTime(sample); \ |
180 } while (0) | 193 } while (0) |
181 | 194 |
182 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. | 195 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. |
183 #define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ | 196 #define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ |
184 scoped_refptr<base::Histogram> counter = \ | 197 static base::Histogram* counter(NULL); \ |
185 base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ | 198 if (!counter) \ |
186 base::Histogram::kUmaTargetedHistogramFlag); \ | 199 counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ |
200 base::Histogram::kUmaTargetedHistogramFlag); \ | |
187 DCHECK_EQ(name, counter->histogram_name()); \ | 201 DCHECK_EQ(name, counter->histogram_name()); \ |
188 if ((sample) < (max) && counter.get()) counter->AddTime(sample); \ | 202 if ((sample) < (max)) counter->AddTime(sample); \ |
189 } while (0) | 203 } while (0) |
190 | 204 |
191 #define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 205 #define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
192 name, sample, 1, 1000000, 50) | 206 name, sample, 1, 1000000, 50) |
193 | 207 |
194 #define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 208 #define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
195 name, sample, 1, 100, 50) | 209 name, sample, 1, 100, 50) |
196 | 210 |
197 #define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 211 #define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
198 name, sample, 1, 10000, 50) | 212 name, sample, 1, 10000, 50) |
199 | 213 |
200 #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ | 214 #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ |
201 scoped_refptr<base::Histogram> counter = \ | 215 static base::Histogram* counter(NULL); \ |
202 base::Histogram::FactoryGet(name, min, max, bucket_count, \ | 216 if (!counter) \ |
203 base::Histogram::kUmaTargetedHistogramFlag); \ | 217 counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \ |
218 base::Histogram::kUmaTargetedHistogramFlag); \ | |
204 DCHECK_EQ(name, counter->histogram_name()); \ | 219 DCHECK_EQ(name, counter->histogram_name()); \ |
205 if (counter.get()) counter->Add(sample); \ | 220 counter->Add(sample); \ |
206 } while (0) | 221 } while (0) |
207 | 222 |
208 #define UMA_HISTOGRAM_MEMORY_KB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 223 #define UMA_HISTOGRAM_MEMORY_KB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
209 name, sample, 1000, 500000, 50) | 224 name, sample, 1000, 500000, 50) |
210 | 225 |
211 #define UMA_HISTOGRAM_MEMORY_MB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 226 #define UMA_HISTOGRAM_MEMORY_MB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
212 name, sample, 1, 1000, 50) | 227 name, sample, 1, 1000, 50) |
213 | 228 |
214 #define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ | 229 #define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ |
215 UMA_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) | 230 UMA_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) |
216 | 231 |
217 #define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \ | 232 #define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \ |
218 scoped_refptr<base::Histogram> counter = \ | 233 static base::Histogram* counter(NULL); \ |
219 base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ | 234 if (!counter) \ |
220 boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag); \ | 235 counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ |
236 boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag); \ | |
221 DCHECK_EQ(name, counter->histogram_name()); \ | 237 DCHECK_EQ(name, counter->histogram_name()); \ |
222 if (counter.get()) counter->Add(sample); \ | 238 counter->Add(sample); \ |
223 } while (0) | 239 } while (0) |
224 | 240 |
225 #define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \ | 241 #define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \ |
226 scoped_refptr<base::Histogram> counter = \ | 242 static base::Histogram* counter(NULL); \ |
227 base::CustomHistogram::FactoryGet(name, custom_ranges, \ | 243 if (!counter) \ |
228 base::Histogram::kUmaTargetedHistogramFlag); \ | 244 counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \ |
245 base::Histogram::kUmaTargetedHistogramFlag); \ | |
229 DCHECK_EQ(name, counter->histogram_name()); \ | 246 DCHECK_EQ(name, counter->histogram_name()); \ |
230 if (counter.get()) counter->Add(sample); \ | 247 counter->Add(sample); \ |
231 } while (0) | 248 } while (0) |
232 | 249 |
233 //------------------------------------------------------------------------------ | 250 //------------------------------------------------------------------------------ |
234 | 251 |
235 class BooleanHistogram; | 252 class BooleanHistogram; |
236 class CustomHistogram; | 253 class CustomHistogram; |
237 class Histogram; | 254 class Histogram; |
238 class LinearHistogram; | 255 class LinearHistogram; |
239 | 256 |
240 class BASE_API Histogram : public base::RefCountedThreadSafe<Histogram> { | 257 class BASE_API Histogram { |
241 public: | 258 public: |
242 typedef int Sample; // Used for samples (and ranges of samples). | 259 typedef int Sample; // Used for samples (and ranges of samples). |
243 typedef int Count; // Used to count samples in a bucket. | 260 typedef int Count; // Used to count samples in a bucket. |
244 static const Sample kSampleType_MAX = INT_MAX; | 261 static const Sample kSampleType_MAX = INT_MAX; |
245 // Initialize maximum number of buckets in histograms as 16,384. | 262 // Initialize maximum number of buckets in histograms as 16,384. |
246 static const size_t kBucketCount_MAX; | 263 static const size_t kBucketCount_MAX; |
247 | 264 |
248 typedef std::vector<Count> Counts; | 265 typedef std::vector<Count> Counts; |
249 typedef std::vector<Sample> Ranges; | 266 typedef std::vector<Sample> Ranges; |
250 | 267 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 // that due to races in histogram accumulation (if a histogram is indeed | 357 // that due to races in histogram accumulation (if a histogram is indeed |
341 // updated on several threads simultaneously), the tallies might mismatch, | 358 // updated on several threads simultaneously), the tallies might mismatch, |
342 // and also the snapshotting code may asynchronously get a mismatch (though | 359 // and also the snapshotting code may asynchronously get a mismatch (though |
343 // generally either race based mismatch cause is VERY rare). | 360 // generally either race based mismatch cause is VERY rare). |
344 int64 redundant_count_; | 361 int64 redundant_count_; |
345 }; | 362 }; |
346 | 363 |
347 //---------------------------------------------------------------------------- | 364 //---------------------------------------------------------------------------- |
348 // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit | 365 // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit |
349 // default underflow bucket. | 366 // default underflow bucket. |
350 static scoped_refptr<Histogram> FactoryGet(const std::string& name, | 367 static Histogram* FactoryGet(const std::string& name, |
351 Sample minimum, Sample maximum, size_t bucket_count, Flags flags); | 368 Sample minimum, |
352 static scoped_refptr<Histogram> FactoryTimeGet(const std::string& name, | 369 Sample maximum, |
353 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count, | 370 size_t bucket_count, |
354 Flags flags); | 371 Flags flags); |
372 static Histogram* FactoryTimeGet(const std::string& name, | |
373 base::TimeDelta minimum, | |
374 base::TimeDelta maximum, | |
375 size_t bucket_count, | |
376 Flags flags); | |
355 | 377 |
356 void Add(int value); | 378 void Add(int value); |
357 | 379 |
358 // This method is an interface, used only by BooleanHistogram. | 380 // This method is an interface, used only by BooleanHistogram. |
359 virtual void AddBoolean(bool value); | 381 virtual void AddBoolean(bool value); |
360 | 382 |
361 // Accept a TimeDelta to increment. | 383 // Accept a TimeDelta to increment. |
362 void AddTime(TimeDelta time) { | 384 void AddTime(TimeDelta time) { |
363 Add(static_cast<int>(time.InMilliseconds())); | 385 Add(static_cast<int>(time.InMilliseconds())); |
364 } | 386 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
419 virtual bool HasConstructorArguments(Sample minimum, Sample maximum, | 441 virtual bool HasConstructorArguments(Sample minimum, Sample maximum, |
420 size_t bucket_count); | 442 size_t bucket_count); |
421 | 443 |
422 virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum, | 444 virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum, |
423 TimeDelta maximum, | 445 TimeDelta maximum, |
424 size_t bucket_count); | 446 size_t bucket_count); |
425 // Return true iff the range_checksum_ matches current ranges_ vector. | 447 // Return true iff the range_checksum_ matches current ranges_ vector. |
426 bool HasValidRangeChecksum() const; | 448 bool HasValidRangeChecksum() const; |
427 | 449 |
428 protected: | 450 protected: |
429 friend class base::RefCountedThreadSafe<Histogram>; | |
430 Histogram(const std::string& name, Sample minimum, | 451 Histogram(const std::string& name, Sample minimum, |
431 Sample maximum, size_t bucket_count); | 452 Sample maximum, size_t bucket_count); |
432 Histogram(const std::string& name, TimeDelta minimum, | 453 Histogram(const std::string& name, TimeDelta minimum, |
433 TimeDelta maximum, size_t bucket_count); | 454 TimeDelta maximum, size_t bucket_count); |
434 | 455 |
435 virtual ~Histogram(); | 456 virtual ~Histogram(); |
436 | 457 |
437 // Initialize ranges_ mapping. | 458 // Initialize ranges_ mapping. |
438 void InitializeBucketRange(); | 459 void InitializeBucketRange(); |
439 | 460 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
473 | 494 |
474 virtual uint32 CalculateRangeChecksum() const; | 495 virtual uint32 CalculateRangeChecksum() const; |
475 | 496 |
476 private: | 497 private: |
477 // Allow tests to corrupt our innards for testing purposes. | 498 // Allow tests to corrupt our innards for testing purposes. |
478 FRIEND_TEST(HistogramTest, CorruptBucketBounds); | 499 FRIEND_TEST(HistogramTest, CorruptBucketBounds); |
479 FRIEND_TEST(HistogramTest, CorruptSampleCounts); | 500 FRIEND_TEST(HistogramTest, CorruptSampleCounts); |
480 FRIEND_TEST(HistogramTest, Crc32SampleHash); | 501 FRIEND_TEST(HistogramTest, Crc32SampleHash); |
481 FRIEND_TEST(HistogramTest, Crc32TableTest); | 502 FRIEND_TEST(HistogramTest, Crc32TableTest); |
482 | 503 |
504 friend class StatisticsRecorder; // To allow it to delete duplicates. | |
505 | |
483 // Post constructor initialization. | 506 // Post constructor initialization. |
484 void Initialize(); | 507 void Initialize(); |
485 | 508 |
486 // Checksum function for accumulating range values into a checksum. | 509 // Checksum function for accumulating range values into a checksum. |
487 static uint32 Crc32(uint32 sum, Sample range); | 510 static uint32 Crc32(uint32 sum, Sample range); |
488 | 511 |
489 //---------------------------------------------------------------------------- | 512 //---------------------------------------------------------------------------- |
490 // Helpers for emitting Ascii graphic. Each method appends data to output. | 513 // Helpers for emitting Ascii graphic. Each method appends data to output. |
491 | 514 |
492 // Find out how large the (graphically) the largest bucket will appear to be. | 515 // Find out how large the (graphically) the largest bucket will appear to be. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
548 //------------------------------------------------------------------------------ | 571 //------------------------------------------------------------------------------ |
549 | 572 |
550 // LinearHistogram is a more traditional histogram, with evenly spaced | 573 // LinearHistogram is a more traditional histogram, with evenly spaced |
551 // buckets. | 574 // buckets. |
552 class BASE_API LinearHistogram : public Histogram { | 575 class BASE_API LinearHistogram : public Histogram { |
553 public: | 576 public: |
554 virtual ~LinearHistogram(); | 577 virtual ~LinearHistogram(); |
555 | 578 |
556 /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit | 579 /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit |
557 default underflow bucket. */ | 580 default underflow bucket. */ |
558 static scoped_refptr<Histogram> FactoryGet(const std::string& name, | 581 static Histogram* FactoryGet(const std::string& name, |
559 Sample minimum, Sample maximum, size_t bucket_count, Flags flags); | 582 Sample minimum, |
560 static scoped_refptr<Histogram> FactoryTimeGet(const std::string& name, | 583 Sample maximum, |
561 TimeDelta minimum, TimeDelta maximum, size_t bucket_count, | 584 size_t bucket_count, |
562 Flags flags); | 585 Flags flags); |
586 static Histogram* FactoryTimeGet(const std::string& name, | |
587 TimeDelta minimum, | |
588 TimeDelta maximum, | |
589 size_t bucket_count, | |
590 Flags flags); | |
563 | 591 |
564 // Overridden from Histogram: | 592 // Overridden from Histogram: |
565 virtual ClassType histogram_type() const; | 593 virtual ClassType histogram_type() const; |
566 | 594 |
567 // Store a list of number/text values for use in rendering the histogram. | 595 // Store a list of number/text values for use in rendering the histogram. |
568 // The last element in the array has a null in its "description" slot. | 596 // The last element in the array has a null in its "description" slot. |
569 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]); | 597 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]); |
570 | 598 |
571 protected: | 599 protected: |
572 LinearHistogram(const std::string& name, Sample minimum, | 600 LinearHistogram(const std::string& name, Sample minimum, |
(...skipping 22 matching lines...) Expand all Loading... | |
595 BucketDescriptionMap bucket_description_; | 623 BucketDescriptionMap bucket_description_; |
596 | 624 |
597 DISALLOW_COPY_AND_ASSIGN(LinearHistogram); | 625 DISALLOW_COPY_AND_ASSIGN(LinearHistogram); |
598 }; | 626 }; |
599 | 627 |
600 //------------------------------------------------------------------------------ | 628 //------------------------------------------------------------------------------ |
601 | 629 |
602 // BooleanHistogram is a histogram for booleans. | 630 // BooleanHistogram is a histogram for booleans. |
603 class BASE_API BooleanHistogram : public LinearHistogram { | 631 class BASE_API BooleanHistogram : public LinearHistogram { |
604 public: | 632 public: |
605 static scoped_refptr<Histogram> FactoryGet(const std::string& name, | 633 static Histogram* FactoryGet(const std::string& name, Flags flags); |
606 Flags flags); | |
607 | 634 |
608 virtual ClassType histogram_type() const; | 635 virtual ClassType histogram_type() const; |
609 | 636 |
610 virtual void AddBoolean(bool value); | 637 virtual void AddBoolean(bool value); |
611 | 638 |
612 private: | 639 private: |
613 explicit BooleanHistogram(const std::string& name); | 640 explicit BooleanHistogram(const std::string& name); |
614 | 641 |
615 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram); | 642 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram); |
616 }; | 643 }; |
617 | 644 |
618 //------------------------------------------------------------------------------ | 645 //------------------------------------------------------------------------------ |
619 | 646 |
620 // CustomHistogram is a histogram for a set of custom integers. | 647 // CustomHistogram is a histogram for a set of custom integers. |
621 class BASE_API CustomHistogram : public Histogram { | 648 class BASE_API CustomHistogram : public Histogram { |
622 public: | 649 public: |
623 | 650 |
624 static scoped_refptr<Histogram> FactoryGet(const std::string& name, | 651 static Histogram* FactoryGet(const std::string& name, |
625 const std::vector<Sample>& custom_ranges, Flags flags); | 652 const std::vector<Sample>& custom_ranges, |
653 Flags flags); | |
626 | 654 |
627 // Overridden from Histogram: | 655 // Overridden from Histogram: |
628 virtual ClassType histogram_type() const; | 656 virtual ClassType histogram_type() const; |
629 | 657 |
630 protected: | 658 protected: |
631 CustomHistogram(const std::string& name, | 659 CustomHistogram(const std::string& name, |
632 const std::vector<Sample>& custom_ranges); | 660 const std::vector<Sample>& custom_ranges); |
633 | 661 |
634 // Initialize ranges_ mapping. | 662 // Initialize ranges_ mapping. |
635 void InitializedCustomBucketRange(const std::vector<Sample>& custom_ranges); | 663 void InitializedCustomBucketRange(const std::vector<Sample>& custom_ranges); |
636 virtual double GetBucketSize(Count current, size_t i) const; | 664 virtual double GetBucketSize(Count current, size_t i) const; |
637 | 665 |
638 DISALLOW_COPY_AND_ASSIGN(CustomHistogram); | 666 DISALLOW_COPY_AND_ASSIGN(CustomHistogram); |
639 }; | 667 }; |
640 | 668 |
641 //------------------------------------------------------------------------------ | 669 //------------------------------------------------------------------------------ |
642 // StatisticsRecorder handles all histograms in the system. It provides a | 670 // StatisticsRecorder handles all histograms in the system. It provides a |
643 // general place for histograms to register, and supports a global API for | 671 // general place for histograms to register, and supports a global API for |
644 // accessing (i.e., dumping, or graphing) the data in all the histograms. | 672 // accessing (i.e., dumping, or graphing) the data in all the histograms. |
645 | 673 |
646 class BASE_API StatisticsRecorder { | 674 class BASE_API StatisticsRecorder { |
647 public: | 675 public: |
648 typedef std::vector<scoped_refptr<Histogram> > Histograms; | 676 typedef std::vector<Histogram*> Histograms; |
649 | 677 |
650 StatisticsRecorder(); | 678 StatisticsRecorder(); |
651 | 679 |
652 ~StatisticsRecorder(); | 680 ~StatisticsRecorder(); |
653 | 681 |
654 // Find out if histograms can now be registered into our list. | 682 // Find out if histograms can now be registered into our list. |
655 static bool IsActive(); | 683 static bool IsActive(); |
656 | 684 |
657 // Register, or add a new histogram to the collection of statistics. If an | 685 // Register, or add a new histogram to the collection of statistics. If an |
658 // identically named histogram is already registered, then the argument | 686 // identically named histogram is already registered, then the argument |
659 // |histogram| will be replaced by the previously registered value, discarding | 687 // |histogram| will deleted. The returns value is always the registered |
rvargas (doing something else)
2011/04/01 19:20:52
nit: the returned value
jar (doing other things)
2011/04/01 21:50:27
Done.
| |
660 // the referenced argument. | 688 // histogram (either the argument, or the pre-existing registered histogram). |
661 static void RegisterOrDiscardDuplicate(scoped_refptr<Histogram>* histogram); | 689 static Histogram* RegisterOrDeleteDuplicate(Histogram* histogram); |
662 | 690 |
663 // Methods for printing histograms. Only histograms which have query as | 691 // Methods for printing histograms. Only histograms which have query as |
664 // a substring are written to output (an empty string will process all | 692 // a substring are written to output (an empty string will process all |
665 // registered histograms). | 693 // registered histograms). |
666 static void WriteHTMLGraph(const std::string& query, std::string* output); | 694 static void WriteHTMLGraph(const std::string& query, std::string* output); |
667 static void WriteGraph(const std::string& query, std::string* output); | 695 static void WriteGraph(const std::string& query, std::string* output); |
668 | 696 |
669 // Method for extracting histograms which were marked for use by UMA. | 697 // Method for extracting histograms which were marked for use by UMA. |
670 static void GetHistograms(Histograms* output); | 698 static void GetHistograms(Histograms* output); |
671 | 699 |
672 // Find a histogram by name. It matches the exact name. This method is thread | 700 // Find a histogram by name. It matches the exact name. This method is thread |
673 // safe. If a matching histogram is not found, then the |histogram| is | 701 // safe. If a matching histogram is not found, then the |histogram| is |
674 // not changed. | 702 // not changed. |
675 static bool FindHistogram(const std::string& query, | 703 static bool FindHistogram(const std::string& query, Histogram** histogram); |
676 scoped_refptr<Histogram>* histogram); | |
677 | 704 |
678 static bool dump_on_exit() { return dump_on_exit_; } | 705 static bool dump_on_exit() { return dump_on_exit_; } |
679 | 706 |
680 static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; } | 707 static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; } |
681 | 708 |
682 // GetSnapshot copies some of the pointers to registered histograms into the | 709 // GetSnapshot copies some of the pointers to registered histograms into the |
683 // caller supplied vector (Histograms). Only histograms with names matching | 710 // caller supplied vector (Histograms). Only histograms with names matching |
684 // query are returned. The query must be a substring of histogram name for its | 711 // query are returned. The query must be a substring of histogram name for its |
685 // pointer to be copied. | 712 // pointer to be copied. |
686 static void GetSnapshot(const std::string& query, Histograms* snapshot); | 713 static void GetSnapshot(const std::string& query, Histograms* snapshot); |
687 | 714 |
688 | 715 |
689 private: | 716 private: |
690 // We keep all registered histograms in a map, from name to histogram. | 717 // We keep all registered histograms in a map, from name to histogram. |
691 typedef std::map<std::string, scoped_refptr<Histogram> > HistogramMap; | 718 typedef std::map<std::string, Histogram*> HistogramMap; |
692 | 719 |
693 static HistogramMap* histograms_; | 720 static HistogramMap* histograms_; |
694 | 721 |
695 // lock protects access to the above map. | 722 // lock protects access to the above map. |
696 static base::Lock* lock_; | 723 static base::Lock* lock_; |
697 | 724 |
698 // Dump all known histograms to log. | 725 // Dump all known histograms to log. |
699 static bool dump_on_exit_; | 726 static bool dump_on_exit_; |
700 | 727 |
701 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); | 728 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); |
702 }; | 729 }; |
703 | 730 |
704 } // namespace base | 731 } // namespace base |
705 | 732 |
706 #endif // BASE_METRICS_HISTOGRAM_H_ | 733 #endif // BASE_METRICS_HISTOGRAM_H_ |
OLD | NEW |