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