OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_METRICS_HISTOGRAM_H_ | 31 #ifndef BASE_METRICS_HISTOGRAM_H_ |
32 #define BASE_METRICS_HISTOGRAM_H_ | 32 #define BASE_METRICS_HISTOGRAM_H_ |
33 #pragma once | 33 #pragma once |
34 | 34 |
35 #include <map> | 35 #include <map> |
36 #include <string> | 36 #include <string> |
37 #include <vector> | 37 #include <vector> |
38 | 38 |
39 #include "base/gtest_prod_util.h" | |
40 #include "base/ref_counted.h" | 39 #include "base/ref_counted.h" |
41 #include "base/logging.h" | 40 #include "base/logging.h" |
42 #include "base/time.h" | 41 #include "base/time.h" |
43 | 42 |
44 class Lock; | 43 class Lock; |
45 class Pickle; | 44 class Pickle; |
46 | 45 |
47 namespace base { | 46 namespace base { |
48 | 47 |
49 //------------------------------------------------------------------------------ | 48 //------------------------------------------------------------------------------ |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 | 236 |
238 class Histogram : public base::RefCountedThreadSafe<Histogram> { | 237 class Histogram : public base::RefCountedThreadSafe<Histogram> { |
239 public: | 238 public: |
240 typedef int Sample; // Used for samples (and ranges of samples). | 239 typedef int Sample; // Used for samples (and ranges of samples). |
241 typedef int Count; // Used to count samples in a bucket. | 240 typedef int Count; // Used to count samples in a bucket. |
242 static const Sample kSampleType_MAX = INT_MAX; | 241 static const Sample kSampleType_MAX = INT_MAX; |
243 | 242 |
244 typedef std::vector<Count> Counts; | 243 typedef std::vector<Count> Counts; |
245 typedef std::vector<Sample> Ranges; | 244 typedef std::vector<Sample> Ranges; |
246 | 245 |
247 // These enums are used to facilitate deserialization of renderer histograms | 246 /* These enums are meant to facilitate deserialization of renderer histograms |
248 // into the browser. | 247 into the browser. */ |
249 enum ClassType { | 248 enum ClassType { |
250 HISTOGRAM, | 249 HISTOGRAM, |
251 LINEAR_HISTOGRAM, | 250 LINEAR_HISTOGRAM, |
252 BOOLEAN_HISTOGRAM, | 251 BOOLEAN_HISTOGRAM, |
253 CUSTOM_HISTOGRAM, | 252 CUSTOM_HISTOGRAM, |
254 NOT_VALID_IN_RENDERER | 253 NOT_VALID_IN_RENDERER |
255 }; | 254 }; |
256 | 255 |
257 enum BucketLayout { | 256 enum BucketLayout { |
258 EXPONENTIAL, | 257 EXPONENTIAL, |
259 LINEAR, | 258 LINEAR, |
260 CUSTOM | 259 CUSTOM |
261 }; | 260 }; |
262 | 261 |
263 enum Flags { | 262 enum Flags { |
264 kNoFlags = 0, | 263 kNoFlags = 0, |
265 kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded. | 264 kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded. |
266 | 265 |
267 // Indicate that the histogram was pickled to be sent across an IPC Channel. | 266 // Indicate that the histogram was pickled to be sent across an IPC Channel. |
268 // If we observe this flag on a histogram being aggregated into after IPC, | 267 // If we observe this flag on a histogram being aggregated into after IPC, |
269 // then we are running in a single process mode, and the aggregation should | 268 // then we are running in a single process mode, and the aggregation should |
270 // not take place (as we would be aggregating back into the source | 269 // not take place (as we would be aggregating back into the source |
271 // histogram!). | 270 // histogram!). |
272 kIPCSerializationSourceFlag = 0x10, | 271 kIPCSerializationSourceFlag = 0x10, |
273 | 272 |
274 kHexRangePrintingFlag = 0x8000, // Fancy bucket-naming supported. | 273 kHexRangePrintingFlag = 0x8000, // Fancy bucket-naming supported. |
275 }; | 274 }; |
276 | 275 |
277 enum Inconsistencies { | |
278 NO_INCONSISTENCIES = 0x0, | |
279 RANGE_CHECKSUM_ERROR = 0x1, | |
280 BUCKET_ORDER_ERROR = 0x2, | |
281 COUNT_HIGH_ERROR = 0x4, | |
282 COUNT_LOW_ERROR = 0x8, | |
283 | |
284 NEVER_EXCEEDED_VALUE = 0x10 | |
285 }; | |
286 | |
287 struct DescriptionPair { | 276 struct DescriptionPair { |
288 Sample sample; | 277 Sample sample; |
289 const char* description; // Null means end of a list of pairs. | 278 const char* description; // Null means end of a list of pairs. |
290 }; | 279 }; |
291 | 280 |
292 //---------------------------------------------------------------------------- | 281 //---------------------------------------------------------------------------- |
293 // Statistic values, developed over the life of the histogram. | 282 // Statistic values, developed over the life of the histogram. |
294 | 283 |
295 class SampleSet { | 284 class SampleSet { |
296 public: | 285 public: |
297 explicit SampleSet(); | 286 explicit SampleSet(); |
298 ~SampleSet(); | 287 ~SampleSet(); |
299 | 288 |
300 // Adjust size of counts_ for use with given histogram. | 289 // Adjust size of counts_ for use with given histogram. |
301 void Resize(const Histogram& histogram); | 290 void Resize(const Histogram& histogram); |
302 void CheckSize(const Histogram& histogram) const; | 291 void CheckSize(const Histogram& histogram) const; |
303 | 292 |
304 // Accessor for histogram to make routine additions. | 293 // Accessor for histogram to make routine additions. |
305 void Accumulate(Sample value, Count count, size_t index); | 294 void Accumulate(Sample value, Count count, size_t index); |
306 | 295 |
307 // Accessor methods. | 296 // Accessor methods. |
308 Count counts(size_t i) const { return counts_[i]; } | 297 Count counts(size_t i) const { return counts_[i]; } |
309 Count TotalCount() const; | 298 Count TotalCount() const; |
310 int64 sum() const { return sum_; } | 299 int64 sum() const { return sum_; } |
311 int64 square_sum() const { return square_sum_; } | 300 int64 square_sum() const { return square_sum_; } |
312 int64 redundant_count() const { return redundant_count_; } | |
313 | 301 |
314 // Arithmetic manipulation of corresponding elements of the set. | 302 // Arithmetic manipulation of corresponding elements of the set. |
315 void Add(const SampleSet& other); | 303 void Add(const SampleSet& other); |
316 void Subtract(const SampleSet& other); | 304 void Subtract(const SampleSet& other); |
317 | 305 |
318 bool Serialize(Pickle* pickle) const; | 306 bool Serialize(Pickle* pickle) const; |
319 bool Deserialize(void** iter, const Pickle& pickle); | 307 bool Deserialize(void** iter, const Pickle& pickle); |
320 | 308 |
321 protected: | 309 protected: |
322 // Actual histogram data is stored in buckets, showing the count of values | 310 // Actual histogram data is stored in buckets, showing the count of values |
323 // that fit into each bucket. | 311 // that fit into each bucket. |
324 Counts counts_; | 312 Counts counts_; |
325 | 313 |
326 // Save simple stats locally. Note that this MIGHT get done in base class | 314 // Save simple stats locally. Note that this MIGHT get done in base class |
327 // without shared memory at some point. | 315 // without shared memory at some point. |
328 int64 sum_; // sum of samples. | 316 int64 sum_; // sum of samples. |
329 int64 square_sum_; // sum of squares of samples. | 317 int64 square_sum_; // sum of squares of samples. |
330 | |
331 private: | |
332 // Allow tests to corrupt our innards for testing purposes. | |
333 FRIEND_TEST(HistogramTest, CorruptSampleCounts); | |
334 | |
335 // To help identify memory corruption, we reduntantly save the number of | |
336 // samples we've accumulated into all of our buckets. We can compare this | |
337 // count to the sum of the counts in all buckets, and detect problems. Note | |
338 // that due to races in histogram accumulation (if a histogram is indeed | |
339 // updated on several threads simultaneously), the tallies might mismatch, | |
340 // and also the snapshotting code may asynchronously get a mismatch (though | |
341 // generally either race based mismatch cause is VERY rare). | |
342 int64 redundant_count_; | |
343 }; | 318 }; |
344 | |
345 //---------------------------------------------------------------------------- | 319 //---------------------------------------------------------------------------- |
346 // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit | 320 // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit |
347 // default underflow bucket. | 321 // default underflow bucket. |
348 static scoped_refptr<Histogram> FactoryGet(const std::string& name, | 322 static scoped_refptr<Histogram> FactoryGet(const std::string& name, |
349 Sample minimum, Sample maximum, size_t bucket_count, Flags flags); | 323 Sample minimum, Sample maximum, size_t bucket_count, Flags flags); |
350 static scoped_refptr<Histogram> FactoryTimeGet(const std::string& name, | 324 static scoped_refptr<Histogram> FactoryTimeGet(const std::string& name, |
351 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count, | 325 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count, |
352 Flags flags); | 326 Flags flags); |
353 | 327 |
354 void Add(int value); | 328 void Add(int value); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 | 360 |
387 // Serialize the given snapshot of a Histogram into a String. Uses | 361 // Serialize the given snapshot of a Histogram into a String. Uses |
388 // Pickle class to flatten the object. | 362 // Pickle class to flatten the object. |
389 static std::string SerializeHistogramInfo(const Histogram& histogram, | 363 static std::string SerializeHistogramInfo(const Histogram& histogram, |
390 const SampleSet& snapshot); | 364 const SampleSet& snapshot); |
391 // The following method accepts a list of pickled histograms and | 365 // The following method accepts a list of pickled histograms and |
392 // builds a histogram and updates shadow copy of histogram data in the | 366 // builds a histogram and updates shadow copy of histogram data in the |
393 // browser process. | 367 // browser process. |
394 static bool DeserializeHistogramInfo(const std::string& histogram_info); | 368 static bool DeserializeHistogramInfo(const std::string& histogram_info); |
395 | 369 |
396 // Check to see if bucket ranges, counts and tallies in the snapshot are | |
397 // consistent with the bucket ranges and checksums in our histogram. This can | |
398 // produce a false-alarm if a race occurred in the reading of the data during | |
399 // a SnapShot process, but should otherwise be false at all times (unless we | |
400 // have memory over-writes, or DRAM failures). | |
401 Inconsistencies FindCorruption(const SampleSet& snapshot) const; | |
402 | |
403 //---------------------------------------------------------------------------- | 370 //---------------------------------------------------------------------------- |
404 // Accessors for factory constuction, serialization and testing. | 371 // Accessors for factory constuction, serialization and testing. |
405 //---------------------------------------------------------------------------- | 372 //---------------------------------------------------------------------------- |
406 virtual ClassType histogram_type() const { return HISTOGRAM; } | 373 virtual ClassType histogram_type() const { return HISTOGRAM; } |
407 const std::string& histogram_name() const { return histogram_name_; } | 374 const std::string& histogram_name() const { return histogram_name_; } |
408 Sample declared_min() const { return declared_min_; } | 375 Sample declared_min() const { return declared_min_; } |
409 Sample declared_max() const { return declared_max_; } | 376 Sample declared_max() const { return declared_max_; } |
410 virtual Sample ranges(size_t i) const { return ranges_[i];} | 377 virtual Sample ranges(size_t i) const { return ranges_[i];} |
411 Sample range_checksum() const { return range_checksum_; } | |
412 virtual size_t bucket_count() const { return bucket_count_; } | 378 virtual size_t bucket_count() const { return bucket_count_; } |
413 // Snapshot the current complete set of sample data. | 379 // Snapshot the current complete set of sample data. |
414 // Override with atomic/locked snapshot if needed. | 380 // Override with atomic/locked snapshot if needed. |
415 virtual void SnapshotSample(SampleSet* sample) const; | 381 virtual void SnapshotSample(SampleSet* sample) const; |
416 | 382 |
417 virtual bool HasConstructorArguments(Sample minimum, Sample maximum, | 383 virtual bool HasConstructorArguments(Sample minimum, Sample maximum, |
418 size_t bucket_count); | 384 size_t bucket_count); |
419 | 385 |
420 virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum, | 386 virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum, |
421 TimeDelta maximum, | 387 TimeDelta maximum, |
(...skipping 14 matching lines...) Expand all Loading... |
436 //---------------------------------------------------------------------------- | 402 //---------------------------------------------------------------------------- |
437 // Methods to override to create histogram with different bucket widths. | 403 // Methods to override to create histogram with different bucket widths. |
438 //---------------------------------------------------------------------------- | 404 //---------------------------------------------------------------------------- |
439 // Initialize ranges_ mapping. | 405 // Initialize ranges_ mapping. |
440 virtual void InitializeBucketRange(); | 406 virtual void InitializeBucketRange(); |
441 // Find bucket to increment for sample value. | 407 // Find bucket to increment for sample value. |
442 virtual size_t BucketIndex(Sample value) const; | 408 virtual size_t BucketIndex(Sample value) const; |
443 // Get normalized size, relative to the ranges_[i]. | 409 // Get normalized size, relative to the ranges_[i]. |
444 virtual double GetBucketSize(Count current, size_t i) const; | 410 virtual double GetBucketSize(Count current, size_t i) const; |
445 | 411 |
446 // Recalculate range_checksum_. | |
447 void ResetRangeChecksum(); | |
448 | |
449 // Return a string description of what goes in a given bucket. | 412 // Return a string description of what goes in a given bucket. |
450 // Most commonly this is the numeric value, but in derived classes it may | 413 // Most commonly this is the numeric value, but in derived classes it may |
451 // be a name (or string description) given to the bucket. | 414 // be a name (or string description) given to the bucket. |
452 virtual const std::string GetAsciiBucketRange(size_t it) const; | 415 virtual const std::string GetAsciiBucketRange(size_t it) const; |
453 | 416 |
454 //---------------------------------------------------------------------------- | 417 //---------------------------------------------------------------------------- |
455 // Methods to override to create thread safe histogram. | 418 // Methods to override to create thread safe histogram. |
456 //---------------------------------------------------------------------------- | 419 //---------------------------------------------------------------------------- |
457 // Update all our internal data, including histogram | 420 // Update all our internal data, including histogram |
458 virtual void Accumulate(Sample value, Count count, size_t index); | 421 virtual void Accumulate(Sample value, Count count, size_t index); |
459 | 422 |
460 //---------------------------------------------------------------------------- | 423 //---------------------------------------------------------------------------- |
461 // Accessors for derived classes. | 424 // Accessors for derived classes. |
462 //---------------------------------------------------------------------------- | 425 //---------------------------------------------------------------------------- |
463 void SetBucketRange(size_t i, Sample value); | 426 void SetBucketRange(size_t i, Sample value); |
464 | 427 |
465 // Validate that ranges_ was created sensibly (top and bottom range | 428 // Validate that ranges_ was created sensibly (top and bottom range |
466 // values relate properly to the declared_min_ and declared_max_).. | 429 // values relate properly to the declared_min_ and declared_max_).. |
467 bool ValidateBucketRanges() const; | 430 bool ValidateBucketRanges() const; |
468 | 431 |
469 private: | 432 private: |
470 // Allow tests to corrupt our innards for testing purposes. | |
471 FRIEND_TEST(HistogramTest, CorruptBucketBounds); | |
472 FRIEND_TEST(HistogramTest, CorruptSampleCounts); | |
473 | |
474 // Post constructor initialization. | 433 // Post constructor initialization. |
475 void Initialize(); | 434 void Initialize(); |
476 | 435 |
477 // Return true iff the range_checksum_ matches current ranges_ vector. | |
478 bool HasValidRangeChecksum() const; | |
479 | |
480 Sample CalculateRangeChecksum() const; | |
481 | |
482 //---------------------------------------------------------------------------- | 436 //---------------------------------------------------------------------------- |
483 // Helpers for emitting Ascii graphic. Each method appends data to output. | 437 // Helpers for emitting Ascii graphic. Each method appends data to output. |
484 | 438 |
485 // Find out how large the (graphically) the largest bucket will appear to be. | 439 // Find out how large the (graphically) the largest bucket will appear to be. |
486 double GetPeakBucketSize(const SampleSet& snapshot) const; | 440 double GetPeakBucketSize(const SampleSet& snapshot) const; |
487 | 441 |
488 // Write a common header message describing this histogram. | 442 // Write a common header message describing this histogram. |
489 void WriteAsciiHeader(const SampleSet& snapshot, | 443 void WriteAsciiHeader(const SampleSet& snapshot, |
490 Count sample_count, std::string* output) const; | 444 Count sample_count, std::string* output) const; |
491 | 445 |
(...skipping 24 matching lines...) Expand all Loading... |
516 | 470 |
517 // Flag the histogram for recording by UMA via metric_services.h. | 471 // Flag the histogram for recording by UMA via metric_services.h. |
518 Flags flags_; | 472 Flags flags_; |
519 | 473 |
520 // For each index, show the least value that can be stored in the | 474 // For each index, show the least value that can be stored in the |
521 // corresponding bucket. We also append one extra element in this array, | 475 // corresponding bucket. We also append one extra element in this array, |
522 // containing kSampleType_MAX, to make calculations easy. | 476 // containing kSampleType_MAX, to make calculations easy. |
523 // The dimension of ranges_ is bucket_count + 1. | 477 // The dimension of ranges_ is bucket_count + 1. |
524 Ranges ranges_; | 478 Ranges ranges_; |
525 | 479 |
526 // For redundancy, we store the sum of all the sample ranges when ranges are | |
527 // generated. If ever there is ever a difference, then the histogram must | |
528 // have been corrupted. | |
529 Sample range_checksum_; | |
530 | |
531 // Finally, provide the state that changes with the addition of each new | 480 // Finally, provide the state that changes with the addition of each new |
532 // sample. | 481 // sample. |
533 SampleSet sample_; | 482 SampleSet sample_; |
534 | 483 |
535 DISALLOW_COPY_AND_ASSIGN(Histogram); | 484 DISALLOW_COPY_AND_ASSIGN(Histogram); |
536 }; | 485 }; |
537 | 486 |
538 //------------------------------------------------------------------------------ | 487 //------------------------------------------------------------------------------ |
539 | 488 |
540 // LinearHistogram is a more traditional histogram, with evenly spaced | 489 // LinearHistogram is a more traditional histogram, with evenly spaced |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 }; | 554 }; |
606 | 555 |
607 //------------------------------------------------------------------------------ | 556 //------------------------------------------------------------------------------ |
608 | 557 |
609 // CustomHistogram is a histogram for a set of custom integers. | 558 // CustomHistogram is a histogram for a set of custom integers. |
610 class CustomHistogram : public Histogram { | 559 class CustomHistogram : public Histogram { |
611 public: | 560 public: |
612 virtual ClassType histogram_type() const; | 561 virtual ClassType histogram_type() const; |
613 | 562 |
614 static scoped_refptr<Histogram> FactoryGet(const std::string& name, | 563 static scoped_refptr<Histogram> FactoryGet(const std::string& name, |
615 const std::vector<Sample>& custom_ranges, Flags flags); | 564 const std::vector<int>& custom_ranges, Flags flags); |
616 | 565 |
617 protected: | 566 protected: |
618 CustomHistogram(const std::string& name, | 567 CustomHistogram(const std::string& name, |
619 const std::vector<Sample>& custom_ranges); | 568 const std::vector<int>& custom_ranges); |
620 | 569 |
621 // Initialize ranges_ mapping. | 570 // Initialize ranges_ mapping. |
622 virtual void InitializeBucketRange(); | 571 virtual void InitializeBucketRange(); |
623 virtual double GetBucketSize(Count current, size_t i) const; | 572 virtual double GetBucketSize(Count current, size_t i) const; |
624 | 573 |
625 private: | 574 private: |
626 // Temporary pointer used during construction/initialization, and then NULLed. | 575 // Temporary pointer used during construction/initialization, and then NULLed. |
627 const std::vector<Sample>* ranges_vector_; | 576 const std::vector<int>* ranges_vector_; |
628 | 577 |
629 DISALLOW_COPY_AND_ASSIGN(CustomHistogram); | 578 DISALLOW_COPY_AND_ASSIGN(CustomHistogram); |
630 }; | 579 }; |
631 | 580 |
632 //------------------------------------------------------------------------------ | 581 //------------------------------------------------------------------------------ |
633 // StatisticsRecorder handles all histograms in the system. It provides a | 582 // StatisticsRecorder handles all histograms in the system. It provides a |
634 // general place for histograms to register, and supports a global API for | 583 // general place for histograms to register, and supports a global API for |
635 // accessing (i.e., dumping, or graphing) the data in all the histograms. | 584 // accessing (i.e., dumping, or graphing) the data in all the histograms. |
636 | 585 |
637 class StatisticsRecorder { | 586 class StatisticsRecorder { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 | 634 |
686 // Dump all known histograms to log. | 635 // Dump all known histograms to log. |
687 static bool dump_on_exit_; | 636 static bool dump_on_exit_; |
688 | 637 |
689 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); | 638 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); |
690 }; | 639 }; |
691 | 640 |
692 } // namespace base | 641 } // namespace base |
693 | 642 |
694 #endif // BASE_METRICS_HISTOGRAM_H_ | 643 #endif // BASE_METRICS_HISTOGRAM_H_ |
OLD | NEW |