Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
michael@0 | 2 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 3 | // found in the LICENSE file. |
michael@0 | 4 | |
michael@0 | 5 | // Histogram is an object that aggregates statistics, and can summarize them in |
michael@0 | 6 | // various forms, including ASCII graphical, HTML, and numerically (as a |
michael@0 | 7 | // vector of numbers corresponding to each of the aggregating buckets). |
michael@0 | 8 | |
michael@0 | 9 | // It supports calls to accumulate either time intervals (which are processed |
michael@0 | 10 | // as integral number of milliseconds), or arbitrary integral units. |
michael@0 | 11 | |
michael@0 | 12 | // The default layout of buckets is exponential. For example, buckets might |
michael@0 | 13 | // contain (sequentially) the count of values in the following intervals: |
michael@0 | 14 | // [0,1), [1,2), [2,4), [4,8), [8,16), [16,32), [32,64), [64,infinity) |
michael@0 | 15 | // That bucket allocation would actually result from construction of a histogram |
michael@0 | 16 | // for values between 1 and 64, with 8 buckets, such as: |
michael@0 | 17 | // Histogram count(L"some name", 1, 64, 8); |
michael@0 | 18 | // Note that the underflow bucket [0,1) and the overflow bucket [64,infinity) |
michael@0 | 19 | // are not counted by the constructor in the user supplied "bucket_count" |
michael@0 | 20 | // argument. |
michael@0 | 21 | // The above example has an exponential ratio of 2 (doubling the bucket width |
michael@0 | 22 | // in each consecutive bucket. The Histogram class automatically calculates |
michael@0 | 23 | // the smallest ratio that it can use to construct the number of buckets |
michael@0 | 24 | // selected in the constructor. An another example, if you had 50 buckets, |
michael@0 | 25 | // and millisecond time values from 1 to 10000, then the ratio between |
michael@0 | 26 | // consecutive bucket widths will be approximately somewhere around the 50th |
michael@0 | 27 | // root of 10000. This approach provides very fine grain (narrow) buckets |
michael@0 | 28 | // at the low end of the histogram scale, but allows the histogram to cover a |
michael@0 | 29 | // gigantic range with the addition of very few buckets. |
michael@0 | 30 | |
michael@0 | 31 | // Histograms use a pattern involving a function static variable, that is a |
michael@0 | 32 | // pointer to a histogram. This static is explicitly initialized on any thread |
michael@0 | 33 | // that detects a uninitialized (NULL) pointer. The potentially racy |
michael@0 | 34 | // initialization is not a problem as it is always set to point to the same |
michael@0 | 35 | // value (i.e., the FactoryGet always returns the same value). FactoryGet |
michael@0 | 36 | // is also completely thread safe, which results in a completely thread safe, |
michael@0 | 37 | // and relatively fast, set of counters. To avoid races at shutdown, the static |
michael@0 | 38 | // pointer is NOT deleted, and we leak the histograms at process termination. |
michael@0 | 39 | |
michael@0 | 40 | #ifndef BASE_METRICS_HISTOGRAM_H_ |
michael@0 | 41 | #define BASE_METRICS_HISTOGRAM_H_ |
michael@0 | 42 | #pragma once |
michael@0 | 43 | |
michael@0 | 44 | #include "mozilla/MemoryReporting.h" |
michael@0 | 45 | |
michael@0 | 46 | #include <map> |
michael@0 | 47 | #include <string> |
michael@0 | 48 | #include <vector> |
michael@0 | 49 | |
michael@0 | 50 | #include "base/time.h" |
michael@0 | 51 | #include "base/lock.h" |
michael@0 | 52 | |
michael@0 | 53 | class Pickle; |
michael@0 | 54 | |
michael@0 | 55 | namespace base { |
michael@0 | 56 | //------------------------------------------------------------------------------ |
michael@0 | 57 | // Provide easy general purpose histogram in a macro, just like stats counters. |
michael@0 | 58 | // The first four macros use 50 buckets. |
michael@0 | 59 | |
michael@0 | 60 | #define HISTOGRAM_TIMES(name, sample) HISTOGRAM_CUSTOM_TIMES( \ |
michael@0 | 61 | name, sample, base::TimeDelta::FromMilliseconds(1), \ |
michael@0 | 62 | base::TimeDelta::FromSeconds(10), 50) |
michael@0 | 63 | |
michael@0 | 64 | #define HISTOGRAM_COUNTS(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ |
michael@0 | 65 | name, sample, 1, 1000000, 50) |
michael@0 | 66 | |
michael@0 | 67 | #define HISTOGRAM_COUNTS_100(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ |
michael@0 | 68 | name, sample, 1, 100, 50) |
michael@0 | 69 | |
michael@0 | 70 | #define HISTOGRAM_COUNTS_10000(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ |
michael@0 | 71 | name, sample, 1, 10000, 50) |
michael@0 | 72 | |
michael@0 | 73 | #define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ |
michael@0 | 74 | static base::Histogram* counter(NULL); \ |
michael@0 | 75 | if (!counter) \ |
michael@0 | 76 | counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \ |
michael@0 | 77 | base::Histogram::kNoFlags); \ |
michael@0 | 78 | DCHECK_EQ(name, counter->histogram_name()); \ |
michael@0 | 79 | counter->Add(sample); \ |
michael@0 | 80 | } while (0) |
michael@0 | 81 | |
michael@0 | 82 | #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ |
michael@0 | 83 | HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) |
michael@0 | 84 | |
michael@0 | 85 | // For folks that need real specific times, use this to select a precise range |
michael@0 | 86 | // of times you want plotted, and the number of buckets you want used. |
michael@0 | 87 | #define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ |
michael@0 | 88 | static base::Histogram* counter(NULL); \ |
michael@0 | 89 | if (!counter) \ |
michael@0 | 90 | counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ |
michael@0 | 91 | base::Histogram::kNoFlags); \ |
michael@0 | 92 | DCHECK_EQ(name, counter->histogram_name()); \ |
michael@0 | 93 | counter->AddTime(sample); \ |
michael@0 | 94 | } while (0) |
michael@0 | 95 | |
michael@0 | 96 | // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. |
michael@0 | 97 | #define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ |
michael@0 | 98 | static base::Histogram* counter(NULL); \ |
michael@0 | 99 | if (!counter) \ |
michael@0 | 100 | counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ |
michael@0 | 101 | base::Histogram::kNoFlags); \ |
michael@0 | 102 | DCHECK_EQ(name, counter->histogram_name()); \ |
michael@0 | 103 | if ((sample) < (max)) counter->AddTime(sample); \ |
michael@0 | 104 | } while (0) |
michael@0 | 105 | |
michael@0 | 106 | // Support histograming of an enumerated value. The samples should always be |
michael@0 | 107 | // less than boundary_value. |
michael@0 | 108 | |
michael@0 | 109 | #define HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \ |
michael@0 | 110 | static base::Histogram* counter(NULL); \ |
michael@0 | 111 | if (!counter) \ |
michael@0 | 112 | counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ |
michael@0 | 113 | boundary_value + 1, base::Histogram::kNoFlags); \ |
michael@0 | 114 | DCHECK_EQ(name, counter->histogram_name()); \ |
michael@0 | 115 | counter->Add(sample); \ |
michael@0 | 116 | } while (0) |
michael@0 | 117 | |
michael@0 | 118 | #define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \ |
michael@0 | 119 | static base::Histogram* counter(NULL); \ |
michael@0 | 120 | if (!counter) \ |
michael@0 | 121 | counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \ |
michael@0 | 122 | base::Histogram::kNoFlags); \ |
michael@0 | 123 | DCHECK_EQ(name, counter->histogram_name()); \ |
michael@0 | 124 | counter->Add(sample); \ |
michael@0 | 125 | } while (0) |
michael@0 | 126 | |
michael@0 | 127 | |
michael@0 | 128 | //------------------------------------------------------------------------------ |
michael@0 | 129 | // Define Debug vs non-debug flavors of macros. |
michael@0 | 130 | #ifndef NDEBUG |
michael@0 | 131 | |
michael@0 | 132 | #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample) |
michael@0 | 133 | #define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample) |
michael@0 | 134 | #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) HISTOGRAM_PERCENTAGE(\ |
michael@0 | 135 | name, under_one_hundred) |
michael@0 | 136 | #define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \ |
michael@0 | 137 | HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) |
michael@0 | 138 | #define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \ |
michael@0 | 139 | HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) |
michael@0 | 140 | #define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \ |
michael@0 | 141 | HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) |
michael@0 | 142 | #define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) \ |
michael@0 | 143 | HISTOGRAM_ENUMERATION(name, sample, boundary_value) |
michael@0 | 144 | #define DHISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \ |
michael@0 | 145 | HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) |
michael@0 | 146 | |
michael@0 | 147 | #else // NDEBUG |
michael@0 | 148 | |
michael@0 | 149 | #define DHISTOGRAM_TIMES(name, sample) do {} while (0) |
michael@0 | 150 | #define DHISTOGRAM_COUNTS(name, sample) do {} while (0) |
michael@0 | 151 | #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) do {} while (0) |
michael@0 | 152 | #define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \ |
michael@0 | 153 | do {} while (0) |
michael@0 | 154 | #define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \ |
michael@0 | 155 | do {} while (0) |
michael@0 | 156 | #define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \ |
michael@0 | 157 | do {} while (0) |
michael@0 | 158 | #define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) do {} while (0) |
michael@0 | 159 | #define DHISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \ |
michael@0 | 160 | do {} while (0) |
michael@0 | 161 | |
michael@0 | 162 | #endif // NDEBUG |
michael@0 | 163 | |
michael@0 | 164 | //------------------------------------------------------------------------------ |
michael@0 | 165 | // The following macros provide typical usage scenarios for callers that wish |
michael@0 | 166 | // to record histogram data, and have the data submitted/uploaded via UMA. |
michael@0 | 167 | // Not all systems support such UMA, but if they do, the following macros |
michael@0 | 168 | // should work with the service. |
michael@0 | 169 | |
michael@0 | 170 | #define UMA_HISTOGRAM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ |
michael@0 | 171 | name, sample, base::TimeDelta::FromMilliseconds(1), \ |
michael@0 | 172 | base::TimeDelta::FromSeconds(10), 50) |
michael@0 | 173 | |
michael@0 | 174 | #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ |
michael@0 | 175 | name, sample, base::TimeDelta::FromMilliseconds(10), \ |
michael@0 | 176 | base::TimeDelta::FromMinutes(3), 50) |
michael@0 | 177 | |
michael@0 | 178 | // Use this macro when times can routinely be much longer than 10 seconds. |
michael@0 | 179 | #define UMA_HISTOGRAM_LONG_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ |
michael@0 | 180 | name, sample, base::TimeDelta::FromMilliseconds(1), \ |
michael@0 | 181 | base::TimeDelta::FromHours(1), 50) |
michael@0 | 182 | |
michael@0 | 183 | #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ |
michael@0 | 184 | static base::Histogram* counter(NULL); \ |
michael@0 | 185 | if (!counter) \ |
michael@0 | 186 | counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ |
michael@0 | 187 | base::Histogram::kUmaTargetedHistogramFlag); \ |
michael@0 | 188 | DCHECK_EQ(name, counter->histogram_name()); \ |
michael@0 | 189 | counter->AddTime(sample); \ |
michael@0 | 190 | } while (0) |
michael@0 | 191 | |
michael@0 | 192 | // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. |
michael@0 | 193 | #define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ |
michael@0 | 194 | static base::Histogram* counter(NULL); \ |
michael@0 | 195 | if (!counter) \ |
michael@0 | 196 | counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ |
michael@0 | 197 | base::Histogram::kUmaTargetedHistogramFlag); \ |
michael@0 | 198 | DCHECK_EQ(name, counter->histogram_name()); \ |
michael@0 | 199 | if ((sample) < (max)) counter->AddTime(sample); \ |
michael@0 | 200 | } while (0) |
michael@0 | 201 | |
michael@0 | 202 | #define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
michael@0 | 203 | name, sample, 1, 1000000, 50) |
michael@0 | 204 | |
michael@0 | 205 | #define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
michael@0 | 206 | name, sample, 1, 100, 50) |
michael@0 | 207 | |
michael@0 | 208 | #define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
michael@0 | 209 | name, sample, 1, 10000, 50) |
michael@0 | 210 | |
michael@0 | 211 | #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ |
michael@0 | 212 | static base::Histogram* counter(NULL); \ |
michael@0 | 213 | if (!counter) \ |
michael@0 | 214 | counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \ |
michael@0 | 215 | base::Histogram::kUmaTargetedHistogramFlag); \ |
michael@0 | 216 | DCHECK_EQ(name, counter->histogram_name()); \ |
michael@0 | 217 | counter->Add(sample); \ |
michael@0 | 218 | } while (0) |
michael@0 | 219 | |
michael@0 | 220 | #define UMA_HISTOGRAM_MEMORY_KB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
michael@0 | 221 | name, sample, 1000, 500000, 50) |
michael@0 | 222 | |
michael@0 | 223 | #define UMA_HISTOGRAM_MEMORY_MB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
michael@0 | 224 | name, sample, 1, 1000, 50) |
michael@0 | 225 | |
michael@0 | 226 | #define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ |
michael@0 | 227 | UMA_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) |
michael@0 | 228 | |
michael@0 | 229 | #define UMA_HISTOGRAM_BOOLEAN(name, sample) do { \ |
michael@0 | 230 | static base::Histogram* counter(NULL); \ |
michael@0 | 231 | if (!counter) \ |
michael@0 | 232 | counter = base::BooleanHistogram::FactoryGet(name, \ |
michael@0 | 233 | base::Histogram::kUmaTargetedHistogramFlag); \ |
michael@0 | 234 | DCHECK_EQ(name, counter->histogram_name()); \ |
michael@0 | 235 | counter->AddBoolean(sample); \ |
michael@0 | 236 | } while (0) |
michael@0 | 237 | |
michael@0 | 238 | #define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \ |
michael@0 | 239 | static base::Histogram* counter(NULL); \ |
michael@0 | 240 | if (!counter) \ |
michael@0 | 241 | counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ |
michael@0 | 242 | boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag); \ |
michael@0 | 243 | DCHECK_EQ(name, counter->histogram_name()); \ |
michael@0 | 244 | counter->Add(sample); \ |
michael@0 | 245 | } while (0) |
michael@0 | 246 | |
michael@0 | 247 | #define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \ |
michael@0 | 248 | static base::Histogram* counter(NULL); \ |
michael@0 | 249 | if (!counter) \ |
michael@0 | 250 | counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \ |
michael@0 | 251 | base::Histogram::kUmaTargetedHistogramFlag); \ |
michael@0 | 252 | DCHECK_EQ(name, counter->histogram_name()); \ |
michael@0 | 253 | counter->Add(sample); \ |
michael@0 | 254 | } while (0) |
michael@0 | 255 | |
michael@0 | 256 | //------------------------------------------------------------------------------ |
michael@0 | 257 | |
michael@0 | 258 | class BooleanHistogram; |
michael@0 | 259 | class CustomHistogram; |
michael@0 | 260 | class Histogram; |
michael@0 | 261 | class LinearHistogram; |
michael@0 | 262 | |
michael@0 | 263 | class Histogram { |
michael@0 | 264 | public: |
michael@0 | 265 | typedef int Sample; // Used for samples (and ranges of samples). |
michael@0 | 266 | typedef int Count; // Used to count samples in a bucket. |
michael@0 | 267 | static const Sample kSampleType_MAX = INT_MAX; |
michael@0 | 268 | // Initialize maximum number of buckets in histograms as 16,384. |
michael@0 | 269 | static const size_t kBucketCount_MAX; |
michael@0 | 270 | |
michael@0 | 271 | typedef std::vector<Count> Counts; |
michael@0 | 272 | typedef std::vector<Sample> Ranges; |
michael@0 | 273 | |
michael@0 | 274 | // These enums are used to facilitate deserialization of renderer histograms |
michael@0 | 275 | // into the browser. |
michael@0 | 276 | enum ClassType { |
michael@0 | 277 | HISTOGRAM, |
michael@0 | 278 | LINEAR_HISTOGRAM, |
michael@0 | 279 | BOOLEAN_HISTOGRAM, |
michael@0 | 280 | FLAG_HISTOGRAM, |
michael@0 | 281 | CUSTOM_HISTOGRAM, |
michael@0 | 282 | NOT_VALID_IN_RENDERER |
michael@0 | 283 | }; |
michael@0 | 284 | |
michael@0 | 285 | enum BucketLayout { |
michael@0 | 286 | EXPONENTIAL, |
michael@0 | 287 | LINEAR, |
michael@0 | 288 | CUSTOM |
michael@0 | 289 | }; |
michael@0 | 290 | |
michael@0 | 291 | enum Flags { |
michael@0 | 292 | kNoFlags = 0, |
michael@0 | 293 | kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded. |
michael@0 | 294 | kExtendedStatisticsFlag = 0x2, // OK to gather extended statistics on histograms. |
michael@0 | 295 | |
michael@0 | 296 | // Indicate that the histogram was pickled to be sent across an IPC Channel. |
michael@0 | 297 | // If we observe this flag on a histogram being aggregated into after IPC, |
michael@0 | 298 | // then we are running in a single process mode, and the aggregation should |
michael@0 | 299 | // not take place (as we would be aggregating back into the source |
michael@0 | 300 | // histogram!). |
michael@0 | 301 | kIPCSerializationSourceFlag = 0x10, |
michael@0 | 302 | |
michael@0 | 303 | kHexRangePrintingFlag = 0x8000 // Fancy bucket-naming supported. |
michael@0 | 304 | }; |
michael@0 | 305 | |
michael@0 | 306 | enum Inconsistencies { |
michael@0 | 307 | NO_INCONSISTENCIES = 0x0, |
michael@0 | 308 | RANGE_CHECKSUM_ERROR = 0x1, |
michael@0 | 309 | BUCKET_ORDER_ERROR = 0x2, |
michael@0 | 310 | COUNT_HIGH_ERROR = 0x4, |
michael@0 | 311 | COUNT_LOW_ERROR = 0x8, |
michael@0 | 312 | |
michael@0 | 313 | NEVER_EXCEEDED_VALUE = 0x10 |
michael@0 | 314 | }; |
michael@0 | 315 | |
michael@0 | 316 | struct DescriptionPair { |
michael@0 | 317 | Sample sample; |
michael@0 | 318 | const char* description; // Null means end of a list of pairs. |
michael@0 | 319 | }; |
michael@0 | 320 | |
michael@0 | 321 | size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); |
michael@0 | 322 | |
michael@0 | 323 | //---------------------------------------------------------------------------- |
michael@0 | 324 | // Statistic values, developed over the life of the histogram. |
michael@0 | 325 | |
michael@0 | 326 | class SampleSet { |
michael@0 | 327 | public: |
michael@0 | 328 | explicit SampleSet(); |
michael@0 | 329 | ~SampleSet(); |
michael@0 | 330 | |
michael@0 | 331 | // Adjust size of counts_ for use with given histogram. |
michael@0 | 332 | void Resize(const Histogram& histogram); |
michael@0 | 333 | void CheckSize(const Histogram& histogram) const; |
michael@0 | 334 | |
michael@0 | 335 | // Accessor for histogram to make routine additions. |
michael@0 | 336 | void AccumulateWithLinearStats(Sample value, Count count, size_t index); |
michael@0 | 337 | // Alternate routine for exponential histograms. |
michael@0 | 338 | // computeExpensiveStatistics should be true if we want to compute log sums. |
michael@0 | 339 | void AccumulateWithExponentialStats(Sample value, Count count, size_t index, |
michael@0 | 340 | bool computeExtendedStatistics); |
michael@0 | 341 | |
michael@0 | 342 | // Accessor methods. |
michael@0 | 343 | Count counts(size_t i) const { return counts_[i]; } |
michael@0 | 344 | Count TotalCount() const; |
michael@0 | 345 | int64_t sum() const { return sum_; } |
michael@0 | 346 | uint64_t sum_squares() const { return sum_squares_; } |
michael@0 | 347 | double log_sum() const { return log_sum_; } |
michael@0 | 348 | double log_sum_squares() const { return log_sum_squares_; } |
michael@0 | 349 | int64_t redundant_count() const { return redundant_count_; } |
michael@0 | 350 | size_t size() const { return counts_.size(); } |
michael@0 | 351 | |
michael@0 | 352 | // Arithmetic manipulation of corresponding elements of the set. |
michael@0 | 353 | void Add(const SampleSet& other); |
michael@0 | 354 | void Subtract(const SampleSet& other); |
michael@0 | 355 | |
michael@0 | 356 | bool Serialize(Pickle* pickle) const; |
michael@0 | 357 | bool Deserialize(void** iter, const Pickle& pickle); |
michael@0 | 358 | |
michael@0 | 359 | size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf); |
michael@0 | 360 | |
michael@0 | 361 | protected: |
michael@0 | 362 | // Actual histogram data is stored in buckets, showing the count of values |
michael@0 | 363 | // that fit into each bucket. |
michael@0 | 364 | Counts counts_; |
michael@0 | 365 | |
michael@0 | 366 | // Save simple stats locally. Note that this MIGHT get done in base class |
michael@0 | 367 | // without shared memory at some point. |
michael@0 | 368 | int64_t sum_; // sum of samples. |
michael@0 | 369 | uint64_t sum_squares_; // sum of squares of samples. |
michael@0 | 370 | |
michael@0 | 371 | // These fields may or may not be updated at the discretion of the |
michael@0 | 372 | // histogram. We use the natural log and compute ln(sample+1) so that |
michael@0 | 373 | // zeros are handled sanely. |
michael@0 | 374 | double log_sum_; // sum of logs of samples. |
michael@0 | 375 | double log_sum_squares_; // sum of squares of logs of samples |
michael@0 | 376 | |
michael@0 | 377 | private: |
michael@0 | 378 | void Accumulate(Sample value, Count count, size_t index); |
michael@0 | 379 | |
michael@0 | 380 | // To help identify memory corruption, we reduntantly save the number of |
michael@0 | 381 | // samples we've accumulated into all of our buckets. We can compare this |
michael@0 | 382 | // count to the sum of the counts in all buckets, and detect problems. Note |
michael@0 | 383 | // that due to races in histogram accumulation (if a histogram is indeed |
michael@0 | 384 | // updated on several threads simultaneously), the tallies might mismatch, |
michael@0 | 385 | // and also the snapshotting code may asynchronously get a mismatch (though |
michael@0 | 386 | // generally either race based mismatch cause is VERY rare). |
michael@0 | 387 | int64_t redundant_count_; |
michael@0 | 388 | }; |
michael@0 | 389 | |
michael@0 | 390 | //---------------------------------------------------------------------------- |
michael@0 | 391 | // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit |
michael@0 | 392 | // default underflow bucket. |
michael@0 | 393 | static Histogram* FactoryGet(const std::string& name, |
michael@0 | 394 | Sample minimum, |
michael@0 | 395 | Sample maximum, |
michael@0 | 396 | size_t bucket_count, |
michael@0 | 397 | Flags flags); |
michael@0 | 398 | static Histogram* FactoryTimeGet(const std::string& name, |
michael@0 | 399 | base::TimeDelta minimum, |
michael@0 | 400 | base::TimeDelta maximum, |
michael@0 | 401 | size_t bucket_count, |
michael@0 | 402 | Flags flags); |
michael@0 | 403 | |
michael@0 | 404 | void Add(int value); |
michael@0 | 405 | void Subtract(int value); |
michael@0 | 406 | |
michael@0 | 407 | // This method is an interface, used only by BooleanHistogram. |
michael@0 | 408 | virtual void AddBoolean(bool value); |
michael@0 | 409 | |
michael@0 | 410 | // Accept a TimeDelta to increment. |
michael@0 | 411 | void AddTime(TimeDelta time) { |
michael@0 | 412 | Add(static_cast<int>(time.InMilliseconds())); |
michael@0 | 413 | } |
michael@0 | 414 | |
michael@0 | 415 | virtual void AddSampleSet(const SampleSet& sample); |
michael@0 | 416 | |
michael@0 | 417 | void Clear(); |
michael@0 | 418 | |
michael@0 | 419 | // This method is an interface, used only by LinearHistogram. |
michael@0 | 420 | virtual void SetRangeDescriptions(const DescriptionPair descriptions[]); |
michael@0 | 421 | |
michael@0 | 422 | // The following methods provide graphical histogram displays. |
michael@0 | 423 | void WriteHTMLGraph(std::string* output) const; |
michael@0 | 424 | void WriteAscii(bool graph_it, const std::string& newline, |
michael@0 | 425 | std::string* output) const; |
michael@0 | 426 | |
michael@0 | 427 | // Support generic flagging of Histograms. |
michael@0 | 428 | // 0x1 Currently used to mark this histogram to be recorded by UMA.. |
michael@0 | 429 | // 0x8000 means print ranges in hex. |
michael@0 | 430 | void SetFlags(Flags flags) { flags_ = static_cast<Flags> (flags_ | flags); } |
michael@0 | 431 | void ClearFlags(Flags flags) { flags_ = static_cast<Flags>(flags_ & ~flags); } |
michael@0 | 432 | int flags() const { return flags_; } |
michael@0 | 433 | |
michael@0 | 434 | // Convenience methods for serializing/deserializing the histograms. |
michael@0 | 435 | // Histograms from Renderer process are serialized and sent to the browser. |
michael@0 | 436 | // Browser process reconstructs the histogram from the pickled version |
michael@0 | 437 | // accumulates the browser-side shadow copy of histograms (that mirror |
michael@0 | 438 | // histograms created in the renderer). |
michael@0 | 439 | |
michael@0 | 440 | // Serialize the given snapshot of a Histogram into a String. Uses |
michael@0 | 441 | // Pickle class to flatten the object. |
michael@0 | 442 | static std::string SerializeHistogramInfo(const Histogram& histogram, |
michael@0 | 443 | const SampleSet& snapshot); |
michael@0 | 444 | // The following method accepts a list of pickled histograms and |
michael@0 | 445 | // builds a histogram and updates shadow copy of histogram data in the |
michael@0 | 446 | // browser process. |
michael@0 | 447 | static bool DeserializeHistogramInfo(const std::string& histogram_info); |
michael@0 | 448 | |
michael@0 | 449 | // Check to see if bucket ranges, counts and tallies in the snapshot are |
michael@0 | 450 | // consistent with the bucket ranges and checksums in our histogram. This can |
michael@0 | 451 | // produce a false-alarm if a race occurred in the reading of the data during |
michael@0 | 452 | // a SnapShot process, but should otherwise be false at all times (unless we |
michael@0 | 453 | // have memory over-writes, or DRAM failures). |
michael@0 | 454 | virtual Inconsistencies FindCorruption(const SampleSet& snapshot) const; |
michael@0 | 455 | |
michael@0 | 456 | //---------------------------------------------------------------------------- |
michael@0 | 457 | // Accessors for factory constuction, serialization and testing. |
michael@0 | 458 | //---------------------------------------------------------------------------- |
michael@0 | 459 | virtual ClassType histogram_type() const; |
michael@0 | 460 | const std::string& histogram_name() const { return histogram_name_; } |
michael@0 | 461 | Sample declared_min() const { return declared_min_; } |
michael@0 | 462 | Sample declared_max() const { return declared_max_; } |
michael@0 | 463 | virtual Sample ranges(size_t i) const; |
michael@0 | 464 | uint32_t range_checksum() const { return range_checksum_; } |
michael@0 | 465 | virtual size_t bucket_count() const; |
michael@0 | 466 | // Snapshot the current complete set of sample data. |
michael@0 | 467 | // Override with atomic/locked snapshot if needed. |
michael@0 | 468 | virtual void SnapshotSample(SampleSet* sample) const; |
michael@0 | 469 | |
michael@0 | 470 | virtual bool HasConstructorArguments(Sample minimum, Sample maximum, |
michael@0 | 471 | size_t bucket_count); |
michael@0 | 472 | |
michael@0 | 473 | virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum, |
michael@0 | 474 | TimeDelta maximum, |
michael@0 | 475 | size_t bucket_count); |
michael@0 | 476 | // Return true iff the range_checksum_ matches current ranges_ vector. |
michael@0 | 477 | bool HasValidRangeChecksum() const; |
michael@0 | 478 | |
michael@0 | 479 | protected: |
michael@0 | 480 | Histogram(const std::string& name, Sample minimum, |
michael@0 | 481 | Sample maximum, size_t bucket_count); |
michael@0 | 482 | Histogram(const std::string& name, TimeDelta minimum, |
michael@0 | 483 | TimeDelta maximum, size_t bucket_count); |
michael@0 | 484 | |
michael@0 | 485 | virtual ~Histogram(); |
michael@0 | 486 | |
michael@0 | 487 | // Initialize ranges_ mapping. |
michael@0 | 488 | void InitializeBucketRange(); |
michael@0 | 489 | |
michael@0 | 490 | // Method to override to skip the display of the i'th bucket if it's empty. |
michael@0 | 491 | virtual bool PrintEmptyBucket(size_t index) const; |
michael@0 | 492 | |
michael@0 | 493 | //---------------------------------------------------------------------------- |
michael@0 | 494 | // Methods to override to create histogram with different bucket widths. |
michael@0 | 495 | //---------------------------------------------------------------------------- |
michael@0 | 496 | // Find bucket to increment for sample value. |
michael@0 | 497 | virtual size_t BucketIndex(Sample value) const; |
michael@0 | 498 | // Get normalized size, relative to the ranges_[i]. |
michael@0 | 499 | virtual double GetBucketSize(Count current, size_t i) const; |
michael@0 | 500 | |
michael@0 | 501 | // Recalculate range_checksum_. |
michael@0 | 502 | void ResetRangeChecksum(); |
michael@0 | 503 | |
michael@0 | 504 | // Return a string description of what goes in a given bucket. |
michael@0 | 505 | // Most commonly this is the numeric value, but in derived classes it may |
michael@0 | 506 | // be a name (or string description) given to the bucket. |
michael@0 | 507 | virtual const std::string GetAsciiBucketRange(size_t it) const; |
michael@0 | 508 | |
michael@0 | 509 | //---------------------------------------------------------------------------- |
michael@0 | 510 | // Methods to override to create thread safe histogram. |
michael@0 | 511 | //---------------------------------------------------------------------------- |
michael@0 | 512 | // Update all our internal data, including histogram |
michael@0 | 513 | virtual void Accumulate(Sample value, Count count, size_t index); |
michael@0 | 514 | |
michael@0 | 515 | //---------------------------------------------------------------------------- |
michael@0 | 516 | // Accessors for derived classes. |
michael@0 | 517 | //---------------------------------------------------------------------------- |
michael@0 | 518 | void SetBucketRange(size_t i, Sample value); |
michael@0 | 519 | |
michael@0 | 520 | // Validate that ranges_ was created sensibly (top and bottom range |
michael@0 | 521 | // values relate properly to the declared_min_ and declared_max_).. |
michael@0 | 522 | bool ValidateBucketRanges() const; |
michael@0 | 523 | |
michael@0 | 524 | virtual uint32_t CalculateRangeChecksum() const; |
michael@0 | 525 | |
michael@0 | 526 | // Finally, provide the state that changes with the addition of each new |
michael@0 | 527 | // sample. |
michael@0 | 528 | SampleSet sample_; |
michael@0 | 529 | |
michael@0 | 530 | private: |
michael@0 | 531 | friend class StatisticsRecorder; // To allow it to delete duplicates. |
michael@0 | 532 | |
michael@0 | 533 | // Post constructor initialization. |
michael@0 | 534 | void Initialize(); |
michael@0 | 535 | |
michael@0 | 536 | // Checksum function for accumulating range values into a checksum. |
michael@0 | 537 | static uint32_t Crc32(uint32_t sum, Sample range); |
michael@0 | 538 | |
michael@0 | 539 | //---------------------------------------------------------------------------- |
michael@0 | 540 | // Helpers for emitting Ascii graphic. Each method appends data to output. |
michael@0 | 541 | |
michael@0 | 542 | // Find out how large the (graphically) the largest bucket will appear to be. |
michael@0 | 543 | double GetPeakBucketSize(const SampleSet& snapshot) const; |
michael@0 | 544 | |
michael@0 | 545 | // Write a common header message describing this histogram. |
michael@0 | 546 | void WriteAsciiHeader(const SampleSet& snapshot, |
michael@0 | 547 | Count sample_count, std::string* output) const; |
michael@0 | 548 | |
michael@0 | 549 | // Write information about previous, current, and next buckets. |
michael@0 | 550 | // Information such as cumulative percentage, etc. |
michael@0 | 551 | void WriteAsciiBucketContext(const int64_t past, const Count current, |
michael@0 | 552 | const int64_t remaining, const size_t i, |
michael@0 | 553 | std::string* output) const; |
michael@0 | 554 | |
michael@0 | 555 | // Write textual description of the bucket contents (relative to histogram). |
michael@0 | 556 | // Output is the count in the buckets, as well as the percentage. |
michael@0 | 557 | void WriteAsciiBucketValue(Count current, double scaled_sum, |
michael@0 | 558 | std::string* output) const; |
michael@0 | 559 | |
michael@0 | 560 | // Produce actual graph (set of blank vs non blank char's) for a bucket. |
michael@0 | 561 | void WriteAsciiBucketGraph(double current_size, double max_size, |
michael@0 | 562 | std::string* output) const; |
michael@0 | 563 | |
michael@0 | 564 | //---------------------------------------------------------------------------- |
michael@0 | 565 | // Table for generating Crc32 values. |
michael@0 | 566 | static const uint32_t kCrcTable[256]; |
michael@0 | 567 | //---------------------------------------------------------------------------- |
michael@0 | 568 | // Invariant values set at/near construction time |
michael@0 | 569 | |
michael@0 | 570 | // ASCII version of original name given to the constructor. All identically |
michael@0 | 571 | // named instances will be coalesced cross-project. |
michael@0 | 572 | const std::string histogram_name_; |
michael@0 | 573 | Sample declared_min_; // Less than this goes into counts_[0] |
michael@0 | 574 | Sample declared_max_; // Over this goes into counts_[bucket_count_ - 1]. |
michael@0 | 575 | size_t bucket_count_; // Dimension of counts_[]. |
michael@0 | 576 | |
michael@0 | 577 | // Flag the histogram for recording by UMA via metric_services.h. |
michael@0 | 578 | Flags flags_; |
michael@0 | 579 | |
michael@0 | 580 | // For each index, show the least value that can be stored in the |
michael@0 | 581 | // corresponding bucket. We also append one extra element in this array, |
michael@0 | 582 | // containing kSampleType_MAX, to make calculations easy. |
michael@0 | 583 | // The dimension of ranges_ is bucket_count + 1. |
michael@0 | 584 | Ranges ranges_; |
michael@0 | 585 | |
michael@0 | 586 | // For redundancy, we store a checksum of all the sample ranges when ranges |
michael@0 | 587 | // are generated. If ever there is ever a difference, then the histogram must |
michael@0 | 588 | // have been corrupted. |
michael@0 | 589 | uint32_t range_checksum_; |
michael@0 | 590 | |
michael@0 | 591 | DISALLOW_COPY_AND_ASSIGN(Histogram); |
michael@0 | 592 | }; |
michael@0 | 593 | |
michael@0 | 594 | //------------------------------------------------------------------------------ |
michael@0 | 595 | |
michael@0 | 596 | // LinearHistogram is a more traditional histogram, with evenly spaced |
michael@0 | 597 | // buckets. |
michael@0 | 598 | class LinearHistogram : public Histogram { |
michael@0 | 599 | public: |
michael@0 | 600 | virtual ~LinearHistogram(); |
michael@0 | 601 | |
michael@0 | 602 | /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit |
michael@0 | 603 | default underflow bucket. */ |
michael@0 | 604 | static Histogram* FactoryGet(const std::string& name, |
michael@0 | 605 | Sample minimum, |
michael@0 | 606 | Sample maximum, |
michael@0 | 607 | size_t bucket_count, |
michael@0 | 608 | Flags flags); |
michael@0 | 609 | static Histogram* FactoryTimeGet(const std::string& name, |
michael@0 | 610 | TimeDelta minimum, |
michael@0 | 611 | TimeDelta maximum, |
michael@0 | 612 | size_t bucket_count, |
michael@0 | 613 | Flags flags); |
michael@0 | 614 | |
michael@0 | 615 | // Overridden from Histogram: |
michael@0 | 616 | virtual ClassType histogram_type() const; |
michael@0 | 617 | |
michael@0 | 618 | virtual void Accumulate(Sample value, Count count, size_t index); |
michael@0 | 619 | |
michael@0 | 620 | // Store a list of number/text values for use in rendering the histogram. |
michael@0 | 621 | // The last element in the array has a null in its "description" slot. |
michael@0 | 622 | virtual void SetRangeDescriptions(const DescriptionPair descriptions[]); |
michael@0 | 623 | |
michael@0 | 624 | protected: |
michael@0 | 625 | LinearHistogram(const std::string& name, Sample minimum, |
michael@0 | 626 | Sample maximum, size_t bucket_count); |
michael@0 | 627 | |
michael@0 | 628 | LinearHistogram(const std::string& name, TimeDelta minimum, |
michael@0 | 629 | TimeDelta maximum, size_t bucket_count); |
michael@0 | 630 | |
michael@0 | 631 | // Initialize ranges_ mapping. |
michael@0 | 632 | void InitializeBucketRange(); |
michael@0 | 633 | virtual double GetBucketSize(Count current, size_t i) const; |
michael@0 | 634 | |
michael@0 | 635 | // If we have a description for a bucket, then return that. Otherwise |
michael@0 | 636 | // let parent class provide a (numeric) description. |
michael@0 | 637 | virtual const std::string GetAsciiBucketRange(size_t i) const; |
michael@0 | 638 | |
michael@0 | 639 | // Skip printing of name for numeric range if we have a name (and if this is |
michael@0 | 640 | // an empty bucket). |
michael@0 | 641 | virtual bool PrintEmptyBucket(size_t index) const; |
michael@0 | 642 | |
michael@0 | 643 | private: |
michael@0 | 644 | // For some ranges, we store a printable description of a bucket range. |
michael@0 | 645 | // If there is no desciption, then GetAsciiBucketRange() uses parent class |
michael@0 | 646 | // to provide a description. |
michael@0 | 647 | typedef std::map<Sample, std::string> BucketDescriptionMap; |
michael@0 | 648 | BucketDescriptionMap bucket_description_; |
michael@0 | 649 | |
michael@0 | 650 | DISALLOW_COPY_AND_ASSIGN(LinearHistogram); |
michael@0 | 651 | }; |
michael@0 | 652 | |
michael@0 | 653 | //------------------------------------------------------------------------------ |
michael@0 | 654 | |
michael@0 | 655 | // BooleanHistogram is a histogram for booleans. |
michael@0 | 656 | class BooleanHistogram : public LinearHistogram { |
michael@0 | 657 | public: |
michael@0 | 658 | static Histogram* FactoryGet(const std::string& name, Flags flags); |
michael@0 | 659 | |
michael@0 | 660 | virtual ClassType histogram_type() const; |
michael@0 | 661 | |
michael@0 | 662 | virtual void AddBoolean(bool value); |
michael@0 | 663 | |
michael@0 | 664 | virtual void Accumulate(Sample value, Count count, size_t index); |
michael@0 | 665 | |
michael@0 | 666 | protected: |
michael@0 | 667 | explicit BooleanHistogram(const std::string& name); |
michael@0 | 668 | |
michael@0 | 669 | DISALLOW_COPY_AND_ASSIGN(BooleanHistogram); |
michael@0 | 670 | }; |
michael@0 | 671 | |
michael@0 | 672 | //------------------------------------------------------------------------------ |
michael@0 | 673 | |
michael@0 | 674 | // FlagHistogram is like boolean histogram, but only allows a single off/on value. |
michael@0 | 675 | class FlagHistogram : public BooleanHistogram |
michael@0 | 676 | { |
michael@0 | 677 | public: |
michael@0 | 678 | static Histogram *FactoryGet(const std::string &name, Flags flags); |
michael@0 | 679 | |
michael@0 | 680 | virtual ClassType histogram_type() const; |
michael@0 | 681 | |
michael@0 | 682 | virtual void Accumulate(Sample value, Count count, size_t index); |
michael@0 | 683 | |
michael@0 | 684 | virtual void AddSampleSet(const SampleSet& sample); |
michael@0 | 685 | |
michael@0 | 686 | private: |
michael@0 | 687 | explicit FlagHistogram(const std::string &name); |
michael@0 | 688 | bool mSwitched; |
michael@0 | 689 | |
michael@0 | 690 | DISALLOW_COPY_AND_ASSIGN(FlagHistogram); |
michael@0 | 691 | }; |
michael@0 | 692 | |
michael@0 | 693 | //------------------------------------------------------------------------------ |
michael@0 | 694 | |
michael@0 | 695 | // CustomHistogram is a histogram for a set of custom integers. |
michael@0 | 696 | class CustomHistogram : public Histogram { |
michael@0 | 697 | public: |
michael@0 | 698 | |
michael@0 | 699 | static Histogram* FactoryGet(const std::string& name, |
michael@0 | 700 | const std::vector<Sample>& custom_ranges, |
michael@0 | 701 | Flags flags); |
michael@0 | 702 | |
michael@0 | 703 | // Overridden from Histogram: |
michael@0 | 704 | virtual ClassType histogram_type() const; |
michael@0 | 705 | |
michael@0 | 706 | protected: |
michael@0 | 707 | CustomHistogram(const std::string& name, |
michael@0 | 708 | const std::vector<Sample>& custom_ranges); |
michael@0 | 709 | |
michael@0 | 710 | // Initialize ranges_ mapping. |
michael@0 | 711 | void InitializedCustomBucketRange(const std::vector<Sample>& custom_ranges); |
michael@0 | 712 | virtual double GetBucketSize(Count current, size_t i) const; |
michael@0 | 713 | |
michael@0 | 714 | DISALLOW_COPY_AND_ASSIGN(CustomHistogram); |
michael@0 | 715 | }; |
michael@0 | 716 | |
michael@0 | 717 | //------------------------------------------------------------------------------ |
michael@0 | 718 | // StatisticsRecorder handles all histograms in the system. It provides a |
michael@0 | 719 | // general place for histograms to register, and supports a global API for |
michael@0 | 720 | // accessing (i.e., dumping, or graphing) the data in all the histograms. |
michael@0 | 721 | |
michael@0 | 722 | class StatisticsRecorder { |
michael@0 | 723 | public: |
michael@0 | 724 | typedef std::vector<Histogram*> Histograms; |
michael@0 | 725 | |
michael@0 | 726 | StatisticsRecorder(); |
michael@0 | 727 | |
michael@0 | 728 | ~StatisticsRecorder(); |
michael@0 | 729 | |
michael@0 | 730 | // Find out if histograms can now be registered into our list. |
michael@0 | 731 | static bool IsActive(); |
michael@0 | 732 | |
michael@0 | 733 | // Register, or add a new histogram to the collection of statistics. If an |
michael@0 | 734 | // identically named histogram is already registered, then the argument |
michael@0 | 735 | // |histogram| will deleted. The returned value is always the registered |
michael@0 | 736 | // histogram (either the argument, or the pre-existing registered histogram). |
michael@0 | 737 | static Histogram* RegisterOrDeleteDuplicate(Histogram* histogram); |
michael@0 | 738 | |
michael@0 | 739 | // Methods for printing histograms. Only histograms which have query as |
michael@0 | 740 | // a substring are written to output (an empty string will process all |
michael@0 | 741 | // registered histograms). |
michael@0 | 742 | static void WriteHTMLGraph(const std::string& query, std::string* output); |
michael@0 | 743 | static void WriteGraph(const std::string& query, std::string* output); |
michael@0 | 744 | |
michael@0 | 745 | // Method for extracting histograms which were marked for use by UMA. |
michael@0 | 746 | static void GetHistograms(Histograms* output); |
michael@0 | 747 | |
michael@0 | 748 | // Find a histogram by name. It matches the exact name. This method is thread |
michael@0 | 749 | // safe. If a matching histogram is not found, then the |histogram| is |
michael@0 | 750 | // not changed. |
michael@0 | 751 | static bool FindHistogram(const std::string& query, Histogram** histogram); |
michael@0 | 752 | |
michael@0 | 753 | static bool dump_on_exit() { return dump_on_exit_; } |
michael@0 | 754 | |
michael@0 | 755 | static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; } |
michael@0 | 756 | |
michael@0 | 757 | // GetSnapshot copies some of the pointers to registered histograms into the |
michael@0 | 758 | // caller supplied vector (Histograms). Only histograms with names matching |
michael@0 | 759 | // query are returned. The query must be a substring of histogram name for its |
michael@0 | 760 | // pointer to be copied. |
michael@0 | 761 | static void GetSnapshot(const std::string& query, Histograms* snapshot); |
michael@0 | 762 | |
michael@0 | 763 | |
michael@0 | 764 | private: |
michael@0 | 765 | // We keep all registered histograms in a map, from name to histogram. |
michael@0 | 766 | typedef std::map<std::string, Histogram*> HistogramMap; |
michael@0 | 767 | |
michael@0 | 768 | static HistogramMap* histograms_; |
michael@0 | 769 | |
michael@0 | 770 | // lock protects access to the above map. |
michael@0 | 771 | static Lock* lock_; |
michael@0 | 772 | |
michael@0 | 773 | // Dump all known histograms to log. |
michael@0 | 774 | static bool dump_on_exit_; |
michael@0 | 775 | |
michael@0 | 776 | DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); |
michael@0 | 777 | }; |
michael@0 | 778 | |
michael@0 | 779 | } // namespace base |
michael@0 | 780 | |
michael@0 | 781 | #endif // BASE_METRICS_HISTOGRAM_H_ |