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

Side by Side Diff: base/histogram.h

Issue 462027: Use factory to create histograms, and refcounts to track lifetimes... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years 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
« no previous file with comments | « no previous file | base/histogram.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 18 matching lines...) Expand all
29 // gigantic range with the addition of very few buckets. 29 // gigantic range with the addition of very few buckets.
30 30
31 #ifndef BASE_HISTOGRAM_H_ 31 #ifndef BASE_HISTOGRAM_H_
32 #define BASE_HISTOGRAM_H_ 32 #define BASE_HISTOGRAM_H_
33 33
34 #include <map> 34 #include <map>
35 #include <string> 35 #include <string>
36 #include <vector> 36 #include <vector>
37 37
38 #include "base/lock.h" 38 #include "base/lock.h"
39 #include "base/ref_counted.h"
40 #include "base/logging.h"
39 #include "base/time.h" 41 #include "base/time.h"
40 42
41 //------------------------------------------------------------------------------ 43 //------------------------------------------------------------------------------
42 // 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.
43 // The first four macros use 50 buckets. 45 // The first four macros use 50 buckets.
44 46
45 #define HISTOGRAM_TIMES(name, sample) do { \ 47 #define HISTOGRAM_TIMES(name, sample) do { \
46 static Histogram counter((name), base::TimeDelta::FromMilliseconds(1), \ 48 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
47 base::TimeDelta::FromSeconds(10), 50); \ 49 (name), base::TimeDelta::FromMilliseconds(1), \
48 counter.AddTime(sample); \ 50 base::TimeDelta::FromSeconds(10), 50); \
51 counter->AddTime(sample); \
49 } while (0) 52 } while (0)
50 53
51 #define HISTOGRAM_COUNTS(name, sample) do { \ 54 #define HISTOGRAM_COUNTS(name, sample) do { \
52 static Histogram counter((name), 1, 1000000, 50); \ 55 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
53 counter.Add(sample); \ 56 (name), 1, 1000000, 50); \
57 counter->Add(sample); \
54 } while (0) 58 } while (0)
55 59
56 #define HISTOGRAM_COUNTS_100(name, sample) do { \ 60 #define HISTOGRAM_COUNTS_100(name, sample) do { \
57 static Histogram counter((name), 1, 100, 50); \ 61 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
58 counter.Add(sample); \ 62 (name), 1, 100, 50); \
63 counter->Add(sample); \
59 } while (0) 64 } while (0)
60 65
61 #define HISTOGRAM_COUNTS_10000(name, sample) do { \ 66 #define HISTOGRAM_COUNTS_10000(name, sample) do { \
62 static Histogram counter((name), 1, 10000, 50); \ 67 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
63 counter.Add(sample); \ 68 (name), 1, 10000, 50); \
69 counter->Add(sample); \
64 } while (0) 70 } while (0)
65 71
66 #define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ 72 #define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \
67 static Histogram counter((name), min, max, bucket_count); \ 73 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
68 counter.Add(sample); \ 74 (name), min, max, bucket_count); \
75 counter->Add(sample); \
69 } while (0) 76 } while (0)
70 77
71 #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) do { \ 78 #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) do { \
72 static LinearHistogram counter((name), 1, 100, 101); \ 79 static scoped_refptr<Histogram> counter = \
73 counter.Add(under_one_hundred); \ 80 LinearHistogram::LinearHistogramFactoryGet(\
81 (name), 1, 100, 101); \
82 counter->Add(under_one_hundred); \
74 } while (0) 83 } while (0)
75 84
76 // For folks that need real specific times, use this to select a precise range 85 // For folks that need real specific times, use this to select a precise range
77 // of times you want plotted, and the number of buckets you want used. 86 // of times you want plotted, and the number of buckets you want used.
78 #define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ 87 #define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \
79 static Histogram counter((name), min, max, bucket_count); \ 88 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
80 counter.AddTime(sample); \ 89 (name), min, max, bucket_count); \
90 counter->AddTime(sample); \
81 } while (0) 91 } while (0)
82 92
83 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. 93 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES.
84 #define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ 94 #define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \
85 static Histogram counter((name), min, max, bucket_count); \ 95 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
86 if ((sample) < (max)) counter.AddTime(sample); \ 96 (name), min, max, bucket_count); \
97 if ((sample) < (max)) counter->AddTime(sample); \
87 } while (0) 98 } while (0)
88 99
89 //------------------------------------------------------------------------------ 100 //------------------------------------------------------------------------------
90 // This macro set is for a histogram that can support both addition and removal 101 // This macro set is for a histogram that can support both addition and removal
91 // of samples. It should be used to render the accumulated asset allocation 102 // of samples. It should be used to render the accumulated asset allocation
92 // of some samples. For example, it can sample memory allocation sizes, and 103 // of some samples. For example, it can sample memory allocation sizes, and
93 // memory releases (as negative samples). 104 // memory releases (as negative samples).
94 // To simplify the interface, only non-zero values can be sampled, with positive 105 // To simplify the interface, only non-zero values can be sampled, with positive
95 // numbers indicating addition, and negative numbers implying dimunition 106 // numbers indicating addition, and negative numbers implying dimunition
96 // (removal). 107 // (removal).
97 // Note that the underlying ThreadSafeHistogram() uses locking to ensure that 108 // Note that the underlying ThreadSafeHistogram() uses locking to ensure that
98 // counts are precise (no chance of losing an addition or removal event, due to 109 // counts are precise (no chance of losing an addition or removal event, due to
99 // multithread racing). This precision is required to prevent missed-counts from 110 // multithread racing). This precision is required to prevent missed-counts from
100 // resulting in drift, as the calls to Remove() for a given value should always 111 // resulting in drift, as the calls to Remove() for a given value should always
101 // be equal in number or fewer than the corresponding calls to Add(). 112 // be equal in number or fewer than the corresponding calls to Add().
102 113
103 #define ASSET_HISTOGRAM_COUNTS(name, sample) do { \ 114 #define ASSET_HISTOGRAM_COUNTS(name, sample) do { \
104 static ThreadSafeHistogram counter((name), 1, 1000000, 50); \ 115 static scoped_refptr<Histogram> counter = \
116 ThreadSafeHistogram::ThreadSafeHistogramFactoryGet(\
117 (name), 1, 1000000, 50); \
105 if (0 == sample) break; \ 118 if (0 == sample) break; \
106 if (sample >= 0) \ 119 if (sample >= 0) \
107 counter.Add(sample); \ 120 counter->Add(sample); \
108 else\ 121 else\
109 counter.Remove(-sample); \ 122 counter->Remove(-sample); \
110 } while (0) 123 } while (0)
111 124
112 //------------------------------------------------------------------------------ 125 //------------------------------------------------------------------------------
113 // Define Debug vs non-debug flavors of macros. 126 // Define Debug vs non-debug flavors of macros.
114 #ifndef NDEBUG 127 #ifndef NDEBUG
115 128
116 #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample) 129 #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample)
117 #define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample) 130 #define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample)
118 #define DASSET_HISTOGRAM_COUNTS(name, sample) ASSET_HISTOGRAM_COUNTS(name, \ 131 #define DASSET_HISTOGRAM_COUNTS(name, sample) ASSET_HISTOGRAM_COUNTS(name, \
119 sample) 132 sample)
(...skipping 23 matching lines...) Expand all
143 #endif // NDEBUG 156 #endif // NDEBUG
144 157
145 //------------------------------------------------------------------------------ 158 //------------------------------------------------------------------------------
146 // The following macros provide typical usage scenarios for callers that wish 159 // The following macros provide typical usage scenarios for callers that wish
147 // to record histogram data, and have the data submitted/uploaded via UMA. 160 // to record histogram data, and have the data submitted/uploaded via UMA.
148 // Not all systems support such UMA, but if they do, the following macros 161 // Not all systems support such UMA, but if they do, the following macros
149 // should work with the service. 162 // should work with the service.
150 163
151 static const int kUmaTargetedHistogramFlag = 0x1; 164 static const int kUmaTargetedHistogramFlag = 0x1;
152 165
153 // This indicates the histogram is shadow copy of renderer histrogram 166 // This indicates the histogram is pickled to be sent across an IPC Channel.
154 // constructed by unpick method and updated regularly from renderer upload 167 // If we observe this flag during unpickle method, then we are running in a
155 // of histograms. 168 // single process mode.
156 static const int kRendererHistogramFlag = 1 << 4; 169 static const int kIPCSerializationSourceFlag = 1 << 4;
170
171 // Some histograms aren't currently destroyed. Until such users properly
172 // decref those histograms, we will mark there histograms as planned to leak so
173 // that we can catch any user that directly tries to call delete "directly"
174 // rather than using the reference counting features that should take care of
175 // this.
176 // TODO(jar): Make this flag unnecessary!
177 static const int kPlannedLeakFlag = 1 << 5;
157 178
158 #define UMA_HISTOGRAM_TIMES(name, sample) do { \ 179 #define UMA_HISTOGRAM_TIMES(name, sample) do { \
159 static Histogram counter((name), base::TimeDelta::FromMilliseconds(1), \ 180 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
160 base::TimeDelta::FromSeconds(10), 50); \ 181 (name), base::TimeDelta::FromMilliseconds(1), \
161 counter.SetFlags(kUmaTargetedHistogramFlag); \ 182 base::TimeDelta::FromSeconds(10), 50); \
162 counter.AddTime(sample); \ 183 counter->SetFlags(kUmaTargetedHistogramFlag); \
184 counter->AddTime(sample); \
163 } while (0) 185 } while (0)
164 186
165 #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) do { \ 187 #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) do { \
166 static Histogram counter((name), base::TimeDelta::FromMilliseconds(10), \ 188 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
167 base::TimeDelta::FromMinutes(3), 50); \ 189 (name), base::TimeDelta::FromMilliseconds(10), \
168 counter.SetFlags(kUmaTargetedHistogramFlag); \ 190 base::TimeDelta::FromMinutes(3), 50); \
169 counter.AddTime(sample); \ 191 counter->SetFlags(kUmaTargetedHistogramFlag); \
192 counter->AddTime(sample); \
170 } while (0) 193 } while (0)
171 194
172 // Use this macro when times can routinely be much longer than 10 seconds. 195 // Use this macro when times can routinely be much longer than 10 seconds.
173 #define UMA_HISTOGRAM_LONG_TIMES(name, sample) do { \ 196 #define UMA_HISTOGRAM_LONG_TIMES(name, sample) do { \
174 static Histogram counter((name), base::TimeDelta::FromMilliseconds(1), \ 197 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
175 base::TimeDelta::FromHours(1), 50); \ 198 (name), base::TimeDelta::FromMilliseconds(1), \
176 counter.SetFlags(kUmaTargetedHistogramFlag); \ 199 base::TimeDelta::FromHours(1), 50); \
177 counter.AddTime(sample); \ 200 counter->SetFlags(kUmaTargetedHistogramFlag); \
201 counter->AddTime(sample); \
178 } while (0) 202 } while (0)
179 203
180 #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ 204 #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \
181 static Histogram counter((name), min, max, bucket_count); \ 205 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
182 counter.SetFlags(kUmaTargetedHistogramFlag); \ 206 (name), min, max, bucket_count); \
183 counter.AddTime(sample); \ 207 counter->SetFlags(kUmaTargetedHistogramFlag); \
208 counter->AddTime(sample); \
184 } while (0) 209 } while (0)
185 210
186 #define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ 211 #define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \
187 static Histogram counter((name), min, max, bucket_count); \ 212 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
188 counter.SetFlags(kUmaTargetedHistogramFlag); \ 213 (name), min, max, bucket_count); \
189 if ((sample) < (max)) counter.AddTime(sample); \ 214 counter->SetFlags(kUmaTargetedHistogramFlag); \
215 if ((sample) < (max)) counter->AddTime(sample); \
190 } while (0) 216 } while (0)
191 217
192 #define UMA_HISTOGRAM_COUNTS(name, sample) do { \ 218 #define UMA_HISTOGRAM_COUNTS(name, sample) do { \
193 static Histogram counter((name), 1, 1000000, 50); \ 219 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
194 counter.SetFlags(kUmaTargetedHistogramFlag); \ 220 (name), 1, 1000000, 50); \
195 counter.Add(sample); \ 221 counter->SetFlags(kUmaTargetedHistogramFlag); \
222 counter->Add(sample); \
196 } while (0) 223 } while (0)
197 224
198 #define UMA_HISTOGRAM_COUNTS_100(name, sample) do { \ 225 #define UMA_HISTOGRAM_COUNTS_100(name, sample) do { \
199 static Histogram counter((name), 1, 100, 50); \ 226 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
200 counter.SetFlags(kUmaTargetedHistogramFlag); \ 227 (name), 1, 100, 50); \
201 counter.Add(sample); \ 228 counter->SetFlags(kUmaTargetedHistogramFlag); \
229 counter->Add(sample); \
202 } while (0) 230 } while (0)
203 231
204 #define UMA_HISTOGRAM_COUNTS_10000(name, sample) do { \ 232 #define UMA_HISTOGRAM_COUNTS_10000(name, sample) do { \
205 static Histogram counter((name), 1, 10000, 50); \ 233 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
206 counter.SetFlags(kUmaTargetedHistogramFlag); \ 234 (name), 1, 10000, 50); \
207 counter.Add(sample); \ 235 counter->SetFlags(kUmaTargetedHistogramFlag); \
236 counter->Add(sample); \
208 } while (0) 237 } while (0)
209 238
210 #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ 239 #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \
211 static Histogram counter((name), min, max, bucket_count); \ 240 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
212 counter.SetFlags(kUmaTargetedHistogramFlag); \ 241 (name), min, max, bucket_count); \
213 counter.Add(sample); \ 242 counter->SetFlags(kUmaTargetedHistogramFlag); \
243 counter->Add(sample); \
214 } while (0) 244 } while (0)
215 245
216 #define UMA_HISTOGRAM_MEMORY_KB(name, sample) do { \ 246 #define UMA_HISTOGRAM_MEMORY_KB(name, sample) do { \
217 static Histogram counter((name), 1000, 500000, 50); \ 247 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
218 counter.SetFlags(kUmaTargetedHistogramFlag); \ 248 (name), 1000, 500000, 50); \
219 counter.Add(sample); \ 249 counter->SetFlags(kUmaTargetedHistogramFlag); \
250 counter->Add(sample); \
220 } while (0) 251 } while (0)
221 252
222 #define UMA_HISTOGRAM_MEMORY_MB(name, sample) do { \ 253 #define UMA_HISTOGRAM_MEMORY_MB(name, sample) do { \
223 static Histogram counter((name), 1, 1000, 50); \ 254 static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
224 counter.SetFlags(kUmaTargetedHistogramFlag); \ 255 (name), 1, 1000, 50); \
225 counter.Add(sample); \ 256 counter->SetFlags(kUmaTargetedHistogramFlag); \
257 counter->Add(sample); \
226 } while (0) 258 } while (0)
227 259
228 #define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) do { \ 260 #define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) do { \
229 static LinearHistogram counter((name), 1, 100, 101); \ 261 static scoped_refptr<Histogram> counter = \
230 counter.SetFlags(kUmaTargetedHistogramFlag); \ 262 LinearHistogram::LinearHistogramFactoryGet(\
231 counter.Add(under_one_hundred); \ 263 (name), 1, 100, 101); \
264 counter->SetFlags(kUmaTargetedHistogramFlag); \
265 counter->Add(under_one_hundred); \
232 } while (0) 266 } while (0)
233 267
234 //------------------------------------------------------------------------------ 268 //------------------------------------------------------------------------------
235 269
236 class Pickle; 270 class Pickle;
271 class Histogram;
272 class LinearHistogram;
273 class BooleanHistogram;
274 class ThreadSafeHistogram;
237 275
238 class Histogram { 276 namespace disk_cache {
277 class StatsHistogram;
278 }; // namespace disk_cache
279
280
281 class Histogram : public base::RefCountedThreadSafe<Histogram> {
239 public: 282 public:
240 typedef int Sample; // Used for samples (and ranges of samples). 283 typedef int Sample; // Used for samples (and ranges of samples).
241 typedef int Count; // Used to count samples in a bucket. 284 typedef int Count; // Used to count samples in a bucket.
242 static const Sample kSampleType_MAX = INT_MAX; 285 static const Sample kSampleType_MAX = INT_MAX;
243 286
244 typedef std::vector<Count> Counts; 287 typedef std::vector<Count> Counts;
245 typedef std::vector<Sample> Ranges; 288 typedef std::vector<Sample> Ranges;
246 289
247 static const int kHexRangePrintingFlag; 290 static const int kHexRangePrintingFlag;
248 291
292 /* These enums are meant to facilitate deserialization of renderer histograms
293 into the browser. */
294 enum ClassType {
295 HISTOGRAM,
296 LINEAR_HISTOGRAM,
297 BOOLEAN_HISTOGRAM,
298 THREAD_SAFE_HISTOGRAM,
299 NOT_VALID_IN_RENDERER
300 };
301
249 enum BucketLayout { 302 enum BucketLayout {
250 EXPONENTIAL, 303 EXPONENTIAL,
251 LINEAR 304 LINEAR
252 }; 305 };
253 306
307 struct DescriptionPair {
308 Sample sample;
309 const char* description; // Null means end of a list of pairs.
310 };
311
254 //---------------------------------------------------------------------------- 312 //----------------------------------------------------------------------------
255 // Statistic values, developed over the life of the histogram. 313 // Statistic values, developed over the life of the histogram.
256 314
257 class SampleSet { 315 class SampleSet {
258 public: 316 public:
259 explicit SampleSet(); 317 explicit SampleSet();
260 // Adjust size of counts_ for use with given histogram. 318 // Adjust size of counts_ for use with given histogram.
261 void Resize(const Histogram& histogram); 319 void Resize(const Histogram& histogram);
262 void CheckSize(const Histogram& histogram) const; 320 void CheckSize(const Histogram& histogram) const;
263 321
(...skipping 17 matching lines...) Expand all
281 // Actual histogram data is stored in buckets, showing the count of values 339 // Actual histogram data is stored in buckets, showing the count of values
282 // that fit into each bucket. 340 // that fit into each bucket.
283 Counts counts_; 341 Counts counts_;
284 342
285 // Save simple stats locally. Note that this MIGHT get done in base class 343 // Save simple stats locally. Note that this MIGHT get done in base class
286 // without shared memory at some point. 344 // without shared memory at some point.
287 int64 sum_; // sum of samples. 345 int64 sum_; // sum of samples.
288 int64 square_sum_; // sum of squares of samples. 346 int64 square_sum_; // sum of squares of samples.
289 }; 347 };
290 //---------------------------------------------------------------------------- 348 //----------------------------------------------------------------------------
291 349 // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit
292 Histogram(const char* name, Sample minimum, 350 // default underflow bucket.
293 Sample maximum, size_t bucket_count); 351 static scoped_refptr<Histogram> HistogramFactoryGet(const std::string& name,
294 Histogram(const char* name, base::TimeDelta minimum, 352 Sample minimum, Sample maximum, size_t bucket_count);
295 base::TimeDelta maximum, size_t bucket_count); 353 static scoped_refptr<Histogram> HistogramFactoryGet(const std::string& name,
296 virtual ~Histogram(); 354 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count);
297 355
298 void Add(int value); 356 void Add(int value);
357
358 // This method is an interface, used only by BooleanHistogram.
359 virtual void AddBoolean(bool value) { DCHECK(false); }
360
299 // Accept a TimeDelta to increment. 361 // Accept a TimeDelta to increment.
300 void AddTime(base::TimeDelta time) { 362 void AddTime(base::TimeDelta time) {
301 Add(static_cast<int>(time.InMilliseconds())); 363 Add(static_cast<int>(time.InMilliseconds()));
302 } 364 }
303 365
304 void AddSampleSet(const SampleSet& sample); 366 void AddSampleSet(const SampleSet& sample);
305 367
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.
372 virtual void SetRangeDescriptions(const DescriptionPair descriptions[])
373 { DCHECK(false); }
374
306 // The following methods provide graphical histogram displays. 375 // The following methods provide graphical histogram displays.
307 void WriteHTMLGraph(std::string* output) const; 376 void WriteHTMLGraph(std::string* output) const;
308 void WriteAscii(bool graph_it, const std::string& newline, 377 void WriteAscii(bool graph_it, const std::string& newline,
309 std::string* output) const; 378 std::string* output) const;
310 379
311 // Support generic flagging of Histograms. 380 // Support generic flagging of Histograms.
312 // 0x1 Currently used to mark this histogram to be recorded by UMA.. 381 // 0x1 Currently used to mark this histogram to be recorded by UMA..
313 // 0x8000 means print ranges in hex. 382 // 0x8000 means print ranges in hex.
314 void SetFlags(int flags) { flags_ |= flags; } 383 void SetFlags(int flags) { flags_ |= flags; }
315 void ClearFlags(int flags) { flags_ &= ~flags; } 384 void ClearFlags(int flags) { flags_ &= ~flags; }
316 int flags() const { return flags_; } 385 int flags() const { return flags_; }
317 386
318 virtual BucketLayout histogram_type() const { return EXPONENTIAL; }
319
320 // Convenience methods for serializing/deserializing the histograms. 387 // Convenience methods for serializing/deserializing the histograms.
321 // Histograms from Renderer process are serialized and sent to the browser. 388 // Histograms from Renderer process are serialized and sent to the browser.
322 // Browser process reconstructs the histogram from the pickled version 389 // Browser process reconstructs the histogram from the pickled version
323 // accumulates the browser-side shadow copy of histograms (that mirror 390 // accumulates the browser-side shadow copy of histograms (that mirror
324 // histograms created in the renderer). 391 // histograms created in the renderer).
325 392
326 // Serialize the given snapshot of a Histogram into a String. Uses 393 // Serialize the given snapshot of a Histogram into a String. Uses
327 // Pickle class to flatten the object. 394 // Pickle class to flatten the object.
328 static std::string SerializeHistogramInfo(const Histogram& histogram, 395 static std::string SerializeHistogramInfo(const Histogram& histogram,
329 const SampleSet& snapshot); 396 const SampleSet& snapshot);
330 // The following method accepts a list of pickled histograms and 397 // The following method accepts a list of pickled histograms and
331 // builds a histogram and updates shadow copy of histogram data in the 398 // builds a histogram and updates shadow copy of histogram data in the
332 // browser process. 399 // browser process.
333 static bool DeserializeHistogramInfo(const std::string& histogram_info); 400 static bool DeserializeHistogramInfo(const std::string& histogram_info);
334 401
335
336 //---------------------------------------------------------------------------- 402 //----------------------------------------------------------------------------
337 // Accessors for serialization and testing. 403 // Accessors for factory constuction, serialization and testing.
338 //---------------------------------------------------------------------------- 404 //----------------------------------------------------------------------------
405 virtual ClassType histogram_type() const { return HISTOGRAM; }
339 const std::string histogram_name() const { return histogram_name_; } 406 const std::string histogram_name() const { return histogram_name_; }
340 Sample declared_min() const { return declared_min_; } 407 Sample declared_min() const { return declared_min_; }
341 Sample declared_max() const { return declared_max_; } 408 Sample declared_max() const { return declared_max_; }
342 virtual Sample ranges(size_t i) const { return ranges_[i];} 409 virtual Sample ranges(size_t i) const { return ranges_[i];}
343 virtual size_t bucket_count() const { return bucket_count_; } 410 virtual size_t bucket_count() const { return bucket_count_; }
344 // Snapshot the current complete set of sample data. 411 // Snapshot the current complete set of sample data.
345 // Override with atomic/locked snapshot if needed. 412 // Override with atomic/locked snapshot if needed.
346 virtual void SnapshotSample(SampleSet* sample) const; 413 virtual void SnapshotSample(SampleSet* sample) const;
347 414
415 virtual bool HasConstructorArguments(Sample minimum, Sample maximum,
416 size_t bucket_count) {
417 return ((minimum == declared_min_) && (maximum == declared_max_) &&
418 (bucket_count == bucket_count_));
419 }
420
421 virtual bool HasConstructorTimeDeltaArguments(base::TimeDelta minimum,
422 base::TimeDelta maximum, size_t bucket_count) {
423 return ((minimum.InMilliseconds() == declared_min_) &&
424 (maximum.InMilliseconds() == declared_max_) &&
425 (bucket_count == bucket_count_));
426 }
427
348 protected: 428 protected:
429 friend class base::RefCountedThreadSafe<Histogram>;
430 Histogram(const std::string& name, Sample minimum,
431 Sample maximum, size_t bucket_count);
432 Histogram(const std::string& name, base::TimeDelta minimum,
433 base::TimeDelta maximum, size_t bucket_count);
434
435 virtual ~Histogram();
436
349 // Method to override to skip the display of the i'th bucket if it's empty. 437 // Method to override to skip the display of the i'th bucket if it's empty.
350 virtual bool PrintEmptyBucket(size_t index) const { return true; } 438 virtual bool PrintEmptyBucket(size_t index) const { return true; }
351 439
352 //---------------------------------------------------------------------------- 440 //----------------------------------------------------------------------------
353 // Methods to override to create histogram with different bucket widths. 441 // Methods to override to create histogram with different bucket widths.
354 //---------------------------------------------------------------------------- 442 //----------------------------------------------------------------------------
355 // Initialize ranges_ mapping. 443 // Initialize ranges_ mapping.
356 virtual void InitializeBucketRange(); 444 virtual void InitializeBucketRange();
357 // Find bucket to increment for sample value. 445 // Find bucket to increment for sample value.
358 virtual size_t BucketIndex(Sample value) const; 446 virtual size_t BucketIndex(Sample value) const;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 // For each index, show the least value that can be stored in the 515 // For each index, show the least value that can be stored in the
428 // corresponding bucket. We also append one extra element in this array, 516 // corresponding bucket. We also append one extra element in this array,
429 // containing kSampleType_MAX, to make calculations easy. 517 // containing kSampleType_MAX, to make calculations easy.
430 // The dimension of ranges_ is bucket_count + 1. 518 // The dimension of ranges_ is bucket_count + 1.
431 Ranges ranges_; 519 Ranges ranges_;
432 520
433 // Finally, provide the state that changes with the addition of each new 521 // Finally, provide the state that changes with the addition of each new
434 // sample. 522 // sample.
435 SampleSet sample_; 523 SampleSet sample_;
436 524
437 // Indicate if successfully registered.
438 bool registered_;
439
440 DISALLOW_COPY_AND_ASSIGN(Histogram); 525 DISALLOW_COPY_AND_ASSIGN(Histogram);
441 }; 526 };
442 527
443 //------------------------------------------------------------------------------ 528 //------------------------------------------------------------------------------
444 529
445 // LinearHistogram is a more traditional histogram, with evenly spaced 530 // LinearHistogram is a more traditional histogram, with evenly spaced
446 // buckets. 531 // buckets.
447 class LinearHistogram : public Histogram { 532 class LinearHistogram : public Histogram {
448 public: 533 public:
449 struct DescriptionPair { 534 virtual ClassType histogram_type() const { return LINEAR_HISTOGRAM; }
450 Sample sample;
451 const char* description; // Null means end of a list of pairs.
452 };
453 LinearHistogram(const char* name, Sample minimum,
454 Sample maximum, size_t bucket_count);
455
456 LinearHistogram(const char* name, base::TimeDelta minimum,
457 base::TimeDelta maximum, size_t bucket_count);
458 ~LinearHistogram() {}
459 535
460 // Store a list of number/text values for use in rendering the histogram. 536 // Store a list of number/text values for use in rendering the histogram.
461 // The last element in the array has a null in its "description" slot. 537 // The last element in the array has a null in its "description" slot.
462 void SetRangeDescriptions(const DescriptionPair descriptions[]); 538 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
463 539
464 virtual BucketLayout histogram_type() const { return LINEAR; } 540 /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit
541 default underflow bucket. */
542 static scoped_refptr<Histogram> LinearHistogramFactoryGet(
543 const std::string& name, Sample minimum, Sample maximum,
544 size_t bucket_count);
545 static scoped_refptr<Histogram> LinearHistogramFactoryGet(
546 const std::string& name, base::TimeDelta minimum,
547 base::TimeDelta maximum, size_t bucket_count);
465 548
466 protected: 549 protected:
550 LinearHistogram(const std::string& name, Sample minimum,
551 Sample maximum, size_t bucket_count);
552
553 LinearHistogram(const std::string& name, base::TimeDelta minimum,
554 base::TimeDelta maximum, size_t bucket_count);
555
556 virtual ~LinearHistogram() {}
557
467 // Initialize ranges_ mapping. 558 // Initialize ranges_ mapping.
468 virtual void InitializeBucketRange(); 559 virtual void InitializeBucketRange();
469 virtual double GetBucketSize(Count current, size_t i) const; 560 virtual double GetBucketSize(Count current, size_t i) const;
470 561
471 // If we have a description for a bucket, then return that. Otherwise 562 // If we have a description for a bucket, then return that. Otherwise
472 // let parent class provide a (numeric) description. 563 // let parent class provide a (numeric) description.
473 virtual const std::string GetAsciiBucketRange(size_t i) const; 564 virtual const std::string GetAsciiBucketRange(size_t i) const;
474 565
475 // Skip printing of name for numeric range if we have a name (and if this is 566 // Skip printing of name for numeric range if we have a name (and if this is
476 // an empty bucket). 567 // an empty bucket).
477 virtual bool PrintEmptyBucket(size_t index) const; 568 virtual bool PrintEmptyBucket(size_t index) const;
478 569
479 private: 570 private:
480 // For some ranges, we store a printable description of a bucket range. 571 // For some ranges, we store a printable description of a bucket range.
481 // If there is no desciption, then GetAsciiBucketRange() uses parent class 572 // If there is no desciption, then GetAsciiBucketRange() uses parent class
482 // to provide a description. 573 // to provide a description.
483 typedef std::map<Sample, std::string> BucketDescriptionMap; 574 typedef std::map<Sample, std::string> BucketDescriptionMap;
484 BucketDescriptionMap bucket_description_; 575 BucketDescriptionMap bucket_description_;
485 576
486 DISALLOW_COPY_AND_ASSIGN(LinearHistogram); 577 DISALLOW_COPY_AND_ASSIGN(LinearHistogram);
487 }; 578 };
488 579
489 //------------------------------------------------------------------------------ 580 //------------------------------------------------------------------------------
490 581
491 // BooleanHistogram is a histogram for booleans. 582 // BooleanHistogram is a histogram for booleans.
492 class BooleanHistogram : public LinearHistogram { 583 class BooleanHistogram : public LinearHistogram {
493 public: 584 public:
494 explicit BooleanHistogram(const char* name) 585 static scoped_refptr<Histogram> BooleanHistogramFactoryGet(
495 : LinearHistogram(name, 0, 2, 3) { 586 const std::string& name);
587
588 virtual ClassType histogram_type() const { return BOOLEAN_HISTOGRAM; }
589
590 virtual void AddBoolean(bool value) { Add(value ? 1 : 0); }
591
592 private:
593 explicit BooleanHistogram(const std::string& name)
594 : LinearHistogram(name, 1, 2, 3) {
496 } 595 }
497 596
498 void AddBoolean(bool value) { Add(value ? 1 : 0); }
499
500 private:
501 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram); 597 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram);
502 }; 598 };
503 599
504 //------------------------------------------------------------------------------ 600 //------------------------------------------------------------------------------
505 // This section provides implementation for ThreadSafeHistogram. 601 // This section provides implementation for ThreadSafeHistogram.
506 //------------------------------------------------------------------------------ 602 //------------------------------------------------------------------------------
507 603
508 class ThreadSafeHistogram : public Histogram { 604 class ThreadSafeHistogram : public Histogram {
509 public: 605 public:
510 ThreadSafeHistogram(const char* name, Sample minimum, 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,
511 Sample maximum, size_t bucket_count); 617 Sample maximum, size_t bucket_count);
512 618
513 // Provide the analog to Add() 619 virtual ~ThreadSafeHistogram() {}
514 void Remove(int value);
515 620
516 protected:
517 // Provide locked versions to get precise counts. 621 // Provide locked versions to get precise counts.
518 virtual void Accumulate(Sample value, Count count, size_t index); 622 virtual void Accumulate(Sample value, Count count, size_t index);
519 623
520 virtual void SnapshotSample(SampleSet* sample) const; 624 virtual void SnapshotSample(SampleSet* sample) const;
521 625
522 private: 626 private:
523 mutable Lock lock_; 627 mutable Lock lock_;
524 628
525 DISALLOW_COPY_AND_ASSIGN(ThreadSafeHistogram); 629 DISALLOW_COPY_AND_ASSIGN(ThreadSafeHistogram);
526 }; 630 };
527 631
528 //------------------------------------------------------------------------------ 632 //------------------------------------------------------------------------------
529 // StatisticsRecorder handles all histograms in the system. It provides a 633 // StatisticsRecorder handles all histograms in the system. It provides a
530 // general place for histograms to register, and supports a global API for 634 // general place for histograms to register, and supports a global API for
531 // accessing (i.e., dumping, or graphing) the data in all the histograms. 635 // accessing (i.e., dumping, or graphing) the data in all the histograms.
532 636
533 class StatisticsRecorder { 637 class StatisticsRecorder {
534 public: 638 public:
535 typedef std::vector<Histogram*> Histograms; 639 typedef std::vector<scoped_refptr<Histogram> > Histograms;
536 640
537 StatisticsRecorder(); 641 StatisticsRecorder();
538 642
539 ~StatisticsRecorder(); 643 ~StatisticsRecorder();
540 644
541 // Find out if histograms can now be registered into our list. 645 // Find out if histograms can now be registered into our list.
542 static bool WasStarted(); 646 static bool WasStarted();
543 647
544 // Register, or add a new histogram to the collection of statistics. 648 // Register, or add a new histogram to the collection of statistics.
545 // Return true if registered. 649 static void Register(Histogram* histogram);
546 static bool Register(Histogram* histogram);
547 // Unregister, or remove, a histogram from the collection of statistics.
548 static void UnRegister(Histogram* histogram);
549 650
550 // Methods for printing histograms. Only histograms which have query as 651 // Methods for printing histograms. Only histograms which have query as
551 // a substring are written to output (an empty string will process all 652 // a substring are written to output (an empty string will process all
552 // registered histograms). 653 // registered histograms).
553 static void WriteHTMLGraph(const std::string& query, std::string* output); 654 static void WriteHTMLGraph(const std::string& query, std::string* output);
554 static void WriteGraph(const std::string& query, std::string* output); 655 static void WriteGraph(const std::string& query, std::string* output);
555 656
556 // Method for extracting histograms which were marked for use by UMA. 657 // Method for extracting histograms which were marked for use by UMA.
557 static void GetHistograms(Histograms* output); 658 static void GetHistograms(Histograms* output);
558 659
559 // Find a histogram by name. This method is thread safe. 660 // Method for extracting histograms for renderer and the histogram's flag is
560 static Histogram* GetHistogram(const std::string& query); 661 // set to kIPCSerializationSourceFlag.
662 static void GetHistogramsForRenderer(Histograms* output);
663
664 // Find a histogram by name. It matches the exact name. This method is thread
665 // safe.
666 static bool FindHistogram(const std::string& query,
667 scoped_refptr<Histogram>* histogram);
668
669 static bool dump_on_exit() { return dump_on_exit_; }
561 670
562 static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; } 671 static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; }
563 672
564 // GetSnapshot copies some of the pointers to registered histograms into the 673 // GetSnapshot copies some of the pointers to registered histograms into the
565 // caller supplied vector (Histograms). Only histograms with names matching 674 // caller supplied vector (Histograms). Only histograms with names matching
566 // query are returned. The query must be a substring of histogram name for its 675 // query are returned. The query must be a substring of histogram name for its
567 // pointer to be copied. 676 // pointer to be copied.
568 static void GetSnapshot(const std::string& query, Histograms* snapshot); 677 static void GetSnapshot(const std::string& query, Histograms* snapshot);
569 678
570 679
571 private: 680 private:
572 // We keep all registered histograms in a map, from name to histogram. 681 // We keep all registered histograms in a map, from name to histogram.
573 typedef std::map<std::string, Histogram*> HistogramMap; 682 typedef std::map<std::string, scoped_refptr<Histogram> > HistogramMap;
574 683
575 static HistogramMap* histograms_; 684 static HistogramMap* histograms_;
576 685
577 // lock protects access to the above map. 686 // lock protects access to the above map.
578 static Lock* lock_; 687 static Lock* lock_;
579 688
580 // Dump all known histograms to log. 689 // Dump all known histograms to log.
581 static bool dump_on_exit_; 690 static bool dump_on_exit_;
582 691
583 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); 692 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder);
584 }; 693 };
585 694
586 #endif // BASE_HISTOGRAM_H_ 695 #endif // BASE_HISTOGRAM_H_
OLDNEW
« no previous file with comments | « no previous file | base/histogram.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698