OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Histogram is an object that aggregates statistics, and can summarize them in | 5 // Histogram is an object that aggregates statistics, and can summarize them in |
6 // various forms, including ASCII graphical, HTML, and numerically (as a | 6 // various forms, including ASCII graphical, HTML, and numerically (as a |
7 // vector of numbers corresponding to each of the aggregating buckets). | 7 // vector of numbers corresponding to each of the aggregating buckets). |
8 | 8 |
9 // It supports calls to accumulate either time intervals (which are processed | 9 // It supports calls to accumulate either time intervals (which are processed |
10 // as integral number of milliseconds), or arbitrary integral units. | 10 // as integral number of milliseconds), or arbitrary integral units. |
(...skipping 18 matching lines...) Expand all Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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_ |
OLD | NEW |