OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 | 42 |
43 #include <map> | 43 #include <map> |
44 #include <string> | 44 #include <string> |
45 #include <vector> | 45 #include <vector> |
46 | 46 |
47 #include "base/atomicops.h" | 47 #include "base/atomicops.h" |
48 #include "base/base_export.h" | 48 #include "base/base_export.h" |
49 #include "base/compiler_specific.h" | 49 #include "base/compiler_specific.h" |
50 #include "base/gtest_prod_util.h" | 50 #include "base/gtest_prod_util.h" |
51 #include "base/logging.h" | 51 #include "base/logging.h" |
52 #include "base/metrics/bucket_ranges.h" | |
53 #include "base/metrics/histogram_base.h" | 52 #include "base/metrics/histogram_base.h" |
54 #include "base/time.h" | 53 #include "base/time.h" |
55 | 54 |
56 class Pickle; | 55 class Pickle; |
57 class PickleIterator; | 56 class PickleIterator; |
58 | 57 |
59 namespace base { | 58 namespace base { |
60 | 59 |
61 class Lock; | 60 class Lock; |
62 //------------------------------------------------------------------------------ | 61 //------------------------------------------------------------------------------ |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag)) | 311 boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag)) |
313 | 312 |
314 #define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \ | 313 #define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \ |
315 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ | 314 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ |
316 base::CustomHistogram::FactoryGet(name, custom_ranges, \ | 315 base::CustomHistogram::FactoryGet(name, custom_ranges, \ |
317 base::Histogram::kUmaTargetedHistogramFlag)) | 316 base::Histogram::kUmaTargetedHistogramFlag)) |
318 | 317 |
319 //------------------------------------------------------------------------------ | 318 //------------------------------------------------------------------------------ |
320 | 319 |
321 class BooleanHistogram; | 320 class BooleanHistogram; |
322 class BucketRanges; | 321 class CachedRanges; |
323 class CustomHistogram; | 322 class CustomHistogram; |
324 class Histogram; | 323 class Histogram; |
325 class LinearHistogram; | 324 class LinearHistogram; |
326 | 325 |
327 class BASE_EXPORT Histogram : public HistogramBase { | 326 class BASE_EXPORT Histogram : public HistogramBase { |
328 public: | 327 public: |
329 // Initialize maximum number of buckets in histograms as 16,384. | 328 // Initialize maximum number of buckets in histograms as 16,384. |
330 static const size_t kBucketCount_MAX; | 329 static const size_t kBucketCount_MAX; |
331 | 330 |
332 typedef std::vector<Count> Counts; | 331 typedef std::vector<Count> Counts; |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 } | 461 } |
463 | 462 |
464 void AddSampleSet(const SampleSet& sample); | 463 void AddSampleSet(const SampleSet& sample); |
465 | 464 |
466 // This method is an interface, used only by LinearHistogram. | 465 // This method is an interface, used only by LinearHistogram. |
467 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]); | 466 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]); |
468 | 467 |
469 // The following methods provide graphical histogram displays. | 468 // The following methods provide graphical histogram displays. |
470 virtual void WriteHTMLGraph(std::string* output) const OVERRIDE; | 469 virtual void WriteHTMLGraph(std::string* output) const OVERRIDE; |
471 virtual void WriteAscii(std::string* output) const OVERRIDE; | 470 virtual void WriteAscii(std::string* output) const OVERRIDE; |
| 471 void WriteAsciiImpl(bool graph_it, |
| 472 const std::string& newline, |
| 473 std::string* output) const; |
472 | 474 |
473 // Support generic flagging of Histograms. | 475 // Support generic flagging of Histograms. |
474 // 0x1 Currently used to mark this histogram to be recorded by UMA.. | 476 // 0x1 Currently used to mark this histogram to be recorded by UMA.. |
475 // 0x8000 means print ranges in hex. | 477 // 0x8000 means print ranges in hex. |
476 void SetFlags(Flags flags) { flags_ = static_cast<Flags> (flags_ | flags); } | 478 void SetFlags(Flags flags) { flags_ = static_cast<Flags> (flags_ | flags); } |
477 void ClearFlags(Flags flags) { flags_ = static_cast<Flags>(flags_ & ~flags); } | 479 void ClearFlags(Flags flags) { flags_ = static_cast<Flags>(flags_ & ~flags); } |
478 int flags() const { return flags_; } | 480 int flags() const { return flags_; } |
479 | 481 |
480 // Convenience methods for serializing/deserializing the histograms. | 482 // Convenience methods for serializing/deserializing the histograms. |
481 // Histograms from Renderer process are serialized and sent to the browser. | 483 // Histograms from Renderer process are serialized and sent to the browser. |
(...skipping 20 matching lines...) Expand all Loading... |
502 | 504 |
503 //---------------------------------------------------------------------------- | 505 //---------------------------------------------------------------------------- |
504 // Accessors for factory constuction, serialization and testing. | 506 // Accessors for factory constuction, serialization and testing. |
505 //---------------------------------------------------------------------------- | 507 //---------------------------------------------------------------------------- |
506 virtual ClassType histogram_type() const; | 508 virtual ClassType histogram_type() const; |
507 Sample declared_min() const { return declared_min_; } | 509 Sample declared_min() const { return declared_min_; } |
508 Sample declared_max() const { return declared_max_; } | 510 Sample declared_max() const { return declared_max_; } |
509 virtual Sample ranges(size_t i) const; | 511 virtual Sample ranges(size_t i) const; |
510 uint32 range_checksum() const { return range_checksum_; } | 512 uint32 range_checksum() const { return range_checksum_; } |
511 virtual size_t bucket_count() const; | 513 virtual size_t bucket_count() const; |
512 BucketRanges* bucket_ranges() const { return bucket_ranges_; } | 514 CachedRanges* cached_ranges() const { return cached_ranges_; } |
513 void set_bucket_ranges(BucketRanges* bucket_ranges) { | 515 void set_cached_ranges(CachedRanges* cached_ranges) { |
514 bucket_ranges_ = bucket_ranges; | 516 cached_ranges_ = cached_ranges; |
515 } | 517 } |
516 // Snapshot the current complete set of sample data. | 518 // Snapshot the current complete set of sample data. |
517 // Override with atomic/locked snapshot if needed. | 519 // Override with atomic/locked snapshot if needed. |
518 virtual void SnapshotSample(SampleSet* sample) const; | 520 virtual void SnapshotSample(SampleSet* sample) const; |
519 | 521 |
520 virtual bool HasConstructorArguments(Sample minimum, Sample maximum, | 522 virtual bool HasConstructorArguments(Sample minimum, Sample maximum, |
521 size_t bucket_count); | 523 size_t bucket_count); |
522 | 524 |
523 virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum, | 525 virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum, |
524 TimeDelta maximum, | 526 TimeDelta maximum, |
525 size_t bucket_count); | 527 size_t bucket_count); |
526 // Return true iff the range_checksum_ matches current |ranges_| vector in | 528 // Return true iff the range_checksum_ matches current |ranges_| vector in |
527 // |bucket_ranges_|. | 529 // |cached_ranges_|. |
528 bool HasValidRangeChecksum() const; | 530 bool HasValidRangeChecksum() const; |
529 | 531 |
530 protected: | 532 protected: |
531 Histogram(const std::string& name, Sample minimum, | 533 Histogram(const std::string& name, Sample minimum, |
532 Sample maximum, size_t bucket_count); | 534 Sample maximum, size_t bucket_count); |
533 Histogram(const std::string& name, TimeDelta minimum, | 535 Histogram(const std::string& name, TimeDelta minimum, |
534 TimeDelta maximum, size_t bucket_count); | 536 TimeDelta maximum, size_t bucket_count); |
535 | 537 |
536 virtual ~Histogram(); | 538 virtual ~Histogram(); |
537 | 539 |
538 // Serialize the histogram's ranges to |*pickle|, returning true on success. | 540 // Serialize the histogram's ranges to |*pickle|, returning true on success. |
539 // Most subclasses can leave this no-op implementation, but some will want to | 541 // Most subclasses can leave this no-op implementation, but some will want to |
540 // override it, especially if the ranges cannot be re-derived from other | 542 // override it, especially if the ranges cannot be re-derived from other |
541 // serialized parameters. | 543 // serialized parameters. |
542 virtual bool SerializeRanges(Pickle* pickle) const; | 544 virtual bool SerializeRanges(Pickle* pickle) const; |
543 | 545 |
544 // Initialize ranges_ mapping in bucket_ranges_. | 546 // Initialize ranges_ mapping in cached_ranges_. |
545 void InitializeBucketRange(); | 547 void InitializeBucketRange(); |
546 | 548 |
547 // Method to override to skip the display of the i'th bucket if it's empty. | 549 // Method to override to skip the display of the i'th bucket if it's empty. |
548 virtual bool PrintEmptyBucket(size_t index) const; | 550 virtual bool PrintEmptyBucket(size_t index) const; |
549 | 551 |
550 //---------------------------------------------------------------------------- | 552 //---------------------------------------------------------------------------- |
551 // Methods to override to create histogram with different bucket widths. | 553 // Methods to override to create histogram with different bucket widths. |
552 //---------------------------------------------------------------------------- | 554 //---------------------------------------------------------------------------- |
553 // Find bucket to increment for sample value. | 555 // Find bucket to increment for sample value. |
554 virtual size_t BucketIndex(Sample value) const; | 556 virtual size_t BucketIndex(Sample value) const; |
(...skipping 12 matching lines...) Expand all Loading... |
567 // Methods to override to create thread safe histogram. | 569 // Methods to override to create thread safe histogram. |
568 //---------------------------------------------------------------------------- | 570 //---------------------------------------------------------------------------- |
569 // Update all our internal data, including histogram | 571 // Update all our internal data, including histogram |
570 virtual void Accumulate(Sample value, Count count, size_t index); | 572 virtual void Accumulate(Sample value, Count count, size_t index); |
571 | 573 |
572 //---------------------------------------------------------------------------- | 574 //---------------------------------------------------------------------------- |
573 // Accessors for derived classes. | 575 // Accessors for derived classes. |
574 //---------------------------------------------------------------------------- | 576 //---------------------------------------------------------------------------- |
575 void SetBucketRange(size_t i, Sample value); | 577 void SetBucketRange(size_t i, Sample value); |
576 | 578 |
577 // Validate that ranges_ in bucket_ranges_ was created sensibly (top and | 579 // Validate that ranges_ in cached_ranges_ was created sensibly (top and |
578 // bottom range values relate properly to the declared_min_ and | 580 // bottom range values relate properly to the declared_min_ and |
579 // declared_max_). | 581 // declared_max_). |
580 bool ValidateBucketRanges() const; | 582 bool ValidateBucketRanges() const; |
581 | 583 |
582 virtual uint32 CalculateRangeChecksum() const; | 584 virtual uint32 CalculateRangeChecksum() const; |
583 | 585 |
584 private: | 586 private: |
585 // Allow tests to corrupt our innards for testing purposes. | 587 // Allow tests to corrupt our innards for testing purposes. |
586 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptBucketBounds); | 588 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptBucketBounds); |
587 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts); | 589 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts); |
588 FRIEND_TEST_ALL_PREFIXES(HistogramTest, Crc32SampleHash); | 590 FRIEND_TEST_ALL_PREFIXES(HistogramTest, Crc32SampleHash); |
589 FRIEND_TEST_ALL_PREFIXES(HistogramTest, Crc32TableTest); | 591 FRIEND_TEST_ALL_PREFIXES(HistogramTest, Crc32TableTest); |
590 | 592 |
591 friend class StatisticsRecorder; // To allow it to delete duplicates. | 593 friend class StatisticsRecorder; // To allow it to delete duplicates. |
592 | 594 |
593 // Post constructor initialization. | 595 // Post constructor initialization. |
594 void Initialize(); | 596 void Initialize(); |
595 | 597 |
596 // Checksum function for accumulating range values into a checksum. | 598 // Checksum function for accumulating range values into a checksum. |
597 static uint32 Crc32(uint32 sum, Sample range); | 599 static uint32 Crc32(uint32 sum, Sample range); |
598 | 600 |
599 //---------------------------------------------------------------------------- | 601 //---------------------------------------------------------------------------- |
600 // Helpers for emitting Ascii graphic. Each method appends data to output. | 602 // Helpers for emitting Ascii graphic. Each method appends data to output. |
601 | 603 |
602 void WriteAsciiImpl(bool graph_it, | |
603 const std::string& newline, | |
604 std::string* output) const; | |
605 | |
606 // Find out how large the (graphically) the largest bucket will appear to be. | 604 // Find out how large the (graphically) the largest bucket will appear to be. |
607 double GetPeakBucketSize(const SampleSet& snapshot) const; | 605 double GetPeakBucketSize(const SampleSet& snapshot) const; |
608 | 606 |
609 // Write a common header message describing this histogram. | 607 // Write a common header message describing this histogram. |
610 void WriteAsciiHeader(const SampleSet& snapshot, | 608 void WriteAsciiHeader(const SampleSet& snapshot, |
611 Count sample_count, std::string* output) const; | 609 Count sample_count, std::string* output) const; |
612 | 610 |
613 // Write information about previous, current, and next buckets. | 611 // Write information about previous, current, and next buckets. |
614 // Information such as cumulative percentage, etc. | 612 // Information such as cumulative percentage, etc. |
615 void WriteAsciiBucketContext(const int64 past, const Count current, | 613 void WriteAsciiBucketContext(const int64 past, const Count current, |
(...skipping 18 matching lines...) Expand all Loading... |
634 Sample declared_min_; // Less than this goes into counts_[0] | 632 Sample declared_min_; // Less than this goes into counts_[0] |
635 Sample declared_max_; // Over this goes into counts_[bucket_count_ - 1]. | 633 Sample declared_max_; // Over this goes into counts_[bucket_count_ - 1]. |
636 size_t bucket_count_; // Dimension of counts_[]. | 634 size_t bucket_count_; // Dimension of counts_[]. |
637 | 635 |
638 // Flag the histogram for recording by UMA via metric_services.h. | 636 // Flag the histogram for recording by UMA via metric_services.h. |
639 Flags flags_; | 637 Flags flags_; |
640 | 638 |
641 // For each index, show the least value that can be stored in the | 639 // For each index, show the least value that can be stored in the |
642 // corresponding bucket. We also append one extra element in this array, | 640 // corresponding bucket. We also append one extra element in this array, |
643 // containing kSampleType_MAX, to make calculations easy. | 641 // containing kSampleType_MAX, to make calculations easy. |
644 // The dimension of ranges_ in bucket_ranges_ is bucket_count + 1. | 642 // The dimension of ranges_ in cached_ranges_ is bucket_count + 1. |
645 BucketRanges* bucket_ranges_; | 643 CachedRanges* cached_ranges_; |
646 | 644 |
647 // For redundancy, we store a checksum of all the sample ranges when ranges | 645 // For redundancy, we store a checksum of all the sample ranges when ranges |
648 // are generated. If ever there is ever a difference, then the histogram must | 646 // are generated. If ever there is ever a difference, then the histogram must |
649 // have been corrupted. | 647 // have been corrupted. |
650 uint32 range_checksum_; | 648 uint32 range_checksum_; |
651 | 649 |
652 // Finally, provide the state that changes with the addition of each new | 650 // Finally, provide the state that changes with the addition of each new |
653 // sample. | 651 // sample. |
654 SampleSet sample_; | 652 SampleSet sample_; |
655 | 653 |
(...skipping 29 matching lines...) Expand all Loading... |
685 virtual void SetRangeDescriptions( | 683 virtual void SetRangeDescriptions( |
686 const DescriptionPair descriptions[]) OVERRIDE; | 684 const DescriptionPair descriptions[]) OVERRIDE; |
687 | 685 |
688 protected: | 686 protected: |
689 LinearHistogram(const std::string& name, Sample minimum, | 687 LinearHistogram(const std::string& name, Sample minimum, |
690 Sample maximum, size_t bucket_count); | 688 Sample maximum, size_t bucket_count); |
691 | 689 |
692 LinearHistogram(const std::string& name, TimeDelta minimum, | 690 LinearHistogram(const std::string& name, TimeDelta minimum, |
693 TimeDelta maximum, size_t bucket_count); | 691 TimeDelta maximum, size_t bucket_count); |
694 | 692 |
695 // Initialize ranges_ mapping in bucket_ranges_. | 693 // Initialize ranges_ mapping in cached_ranges_. |
696 void InitializeBucketRange(); | 694 void InitializeBucketRange(); |
697 virtual double GetBucketSize(Count current, size_t i) const OVERRIDE; | 695 virtual double GetBucketSize(Count current, size_t i) const OVERRIDE; |
698 | 696 |
699 // If we have a description for a bucket, then return that. Otherwise | 697 // If we have a description for a bucket, then return that. Otherwise |
700 // let parent class provide a (numeric) description. | 698 // let parent class provide a (numeric) description. |
701 virtual const std::string GetAsciiBucketRange(size_t i) const OVERRIDE; | 699 virtual const std::string GetAsciiBucketRange(size_t i) const OVERRIDE; |
702 | 700 |
703 // Skip printing of name for numeric range if we have a name (and if this is | 701 // Skip printing of name for numeric range if we have a name (and if this is |
704 // an empty bucket). | 702 // an empty bucket). |
705 virtual bool PrintEmptyBucket(size_t index) const OVERRIDE; | 703 virtual bool PrintEmptyBucket(size_t index) const OVERRIDE; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 static bool DeserializeRanges(PickleIterator* iter, | 755 static bool DeserializeRanges(PickleIterator* iter, |
758 std::vector<Histogram::Sample>* ranges); | 756 std::vector<Histogram::Sample>* ranges); |
759 | 757 |
760 | 758 |
761 protected: | 759 protected: |
762 CustomHistogram(const std::string& name, | 760 CustomHistogram(const std::string& name, |
763 const std::vector<Sample>& custom_ranges); | 761 const std::vector<Sample>& custom_ranges); |
764 | 762 |
765 virtual bool SerializeRanges(Pickle* pickle) const OVERRIDE; | 763 virtual bool SerializeRanges(Pickle* pickle) const OVERRIDE; |
766 | 764 |
767 // Initialize ranges_ mapping in bucket_ranges_. | 765 // Initialize ranges_ mapping in cached_ranges_. |
768 void InitializedCustomBucketRange(const std::vector<Sample>& custom_ranges); | 766 void InitializedCustomBucketRange(const std::vector<Sample>& custom_ranges); |
769 virtual double GetBucketSize(Count current, size_t i) const OVERRIDE; | 767 virtual double GetBucketSize(Count current, size_t i) const OVERRIDE; |
770 | 768 |
771 DISALLOW_COPY_AND_ASSIGN(CustomHistogram); | 769 DISALLOW_COPY_AND_ASSIGN(CustomHistogram); |
772 }; | 770 }; |
773 | 771 |
| 772 // CachedRanges stores the Ranges vector. Histograms that have same Ranges |
| 773 // vector will use the same CachedRanges object. |
| 774 class BASE_EXPORT CachedRanges { |
| 775 public: |
| 776 typedef std::vector<Histogram::Sample> Ranges; |
| 777 |
| 778 CachedRanges(size_t bucket_count, int initial_value); |
| 779 ~CachedRanges(); |
| 780 |
| 781 //---------------------------------------------------------------------------- |
| 782 // Accessors methods for ranges_ and range_checksum_. |
| 783 //---------------------------------------------------------------------------- |
| 784 size_t size() const { return ranges_.size(); } |
| 785 Histogram::Sample ranges(size_t i) const { return ranges_[i]; } |
| 786 void SetBucketRange(size_t i, Histogram::Sample value); |
| 787 uint32 range_checksum(uint32 checksum) const { return range_checksum_; } |
| 788 void SetRangeChecksum(uint32 checksum) { range_checksum_ = checksum; } |
| 789 |
| 790 // Return true iff |other| object has same ranges_ as |this| object's ranges_. |
| 791 bool Equals(CachedRanges* other) const; |
| 792 |
| 793 private: |
| 794 // Allow tests to corrupt our innards for testing purposes. |
| 795 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptBucketBounds); |
| 796 |
| 797 // A monotonically increasing list of values which determine which bucket to |
| 798 // put a sample into. For each index, show the smallest sample that can be |
| 799 // added to the corresponding bucket. |
| 800 Ranges ranges_; |
| 801 |
| 802 // Checksum for the conntents of ranges_. Used to detect random over-writes |
| 803 // of our data, and to quickly see if some other CachedRanges instance is |
| 804 // possibly Equal() to this instance. |
| 805 uint32 range_checksum_; |
| 806 |
| 807 DISALLOW_COPY_AND_ASSIGN(CachedRanges); |
| 808 }; |
| 809 |
774 } // namespace base | 810 } // namespace base |
775 | 811 |
776 #endif // BASE_METRICS_HISTOGRAM_H_ | 812 #endif // BASE_METRICS_HISTOGRAM_H_ |
OLD | NEW |