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

Side by Side Diff: base/metrics/histogram.h

Issue 6780035: Use lock-free lazy initialization for static histogram references (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 8 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 | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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_
OLDNEW
« no previous file with comments | « base/message_loop.cc ('k') | base/metrics/histogram.cc » ('j') | chrome/browser/jankometer.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698