| 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 |