Chromium Code Reviews| 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 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 364 enum Inconsistencies { | 364 enum Inconsistencies { |
| 365 NO_INCONSISTENCIES = 0x0, | 365 NO_INCONSISTENCIES = 0x0, |
| 366 RANGE_CHECKSUM_ERROR = 0x1, | 366 RANGE_CHECKSUM_ERROR = 0x1, |
| 367 BUCKET_ORDER_ERROR = 0x2, | 367 BUCKET_ORDER_ERROR = 0x2, |
| 368 COUNT_HIGH_ERROR = 0x4, | 368 COUNT_HIGH_ERROR = 0x4, |
| 369 COUNT_LOW_ERROR = 0x8, | 369 COUNT_LOW_ERROR = 0x8, |
| 370 | 370 |
| 371 NEVER_EXCEEDED_VALUE = 0x10 | 371 NEVER_EXCEEDED_VALUE = 0x10 |
| 372 }; | 372 }; |
| 373 | 373 |
| 374 struct DescriptionPair { | |
| 375 Sample sample; | |
| 376 const char* description; // Null means end of a list of pairs. | |
| 377 }; | |
| 378 | |
| 379 //---------------------------------------------------------------------------- | 374 //---------------------------------------------------------------------------- |
| 380 // For a valid histogram, input should follow these restrictions: | 375 // For a valid histogram, input should follow these restrictions: |
| 381 // minimum > 0 (if a minimum below 1 is specified, it will implicitly be | 376 // minimum > 0 (if a minimum below 1 is specified, it will implicitly be |
| 382 // normalized up to 1) | 377 // normalized up to 1) |
| 383 // maximum > minimum | 378 // maximum > minimum |
| 384 // buckets > 2 [minimum buckets needed: underflow, overflow and the range] | 379 // buckets > 2 [minimum buckets needed: underflow, overflow and the range] |
| 385 // Additionally, | 380 // Additionally, |
| 386 // buckets <= (maximum - minimum + 2) - this is to ensure that we don't have | 381 // buckets <= (maximum - minimum + 2) - this is to ensure that we don't have |
| 387 // more buckets than the range of numbers; having more buckets than 1 per | 382 // more buckets than the range of numbers; having more buckets than 1 per |
| 388 // value in the range would be nonsensical. | 383 // value in the range would be nonsensical. |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 407 BucketRanges* ranges); | 402 BucketRanges* ranges); |
| 408 | 403 |
| 409 // This method is an interface, used only by BooleanHistogram. | 404 // This method is an interface, used only by BooleanHistogram. |
| 410 virtual void AddBoolean(bool value); | 405 virtual void AddBoolean(bool value); |
| 411 | 406 |
| 412 // Accept a TimeDelta to increment. | 407 // Accept a TimeDelta to increment. |
| 413 void AddTime(TimeDelta time) { | 408 void AddTime(TimeDelta time) { |
| 414 Add(static_cast<int>(time.InMilliseconds())); | 409 Add(static_cast<int>(time.InMilliseconds())); |
| 415 } | 410 } |
| 416 | 411 |
| 417 void AddSamples(const HistogramSamples& samples); | |
| 418 bool AddSamplesFromPickle(PickleIterator* iter); | |
| 419 | |
| 420 // Convenience methods for serializing/deserializing the histograms. | |
| 421 // Histograms from Renderer process are serialized and sent to the browser. | |
| 422 // Browser process reconstructs the histogram from the pickled version | |
| 423 // accumulates the browser-side shadow copy of histograms (that mirror | |
| 424 // histograms created in the renderer). | |
| 425 | |
| 426 // Serialize the given snapshot of a Histogram into a String. Uses | |
| 427 // Pickle class to flatten the object. | |
| 428 static std::string SerializeHistogramInfo(const Histogram& histogram, | |
| 429 const HistogramSamples& snapshot); | |
| 430 | |
| 431 // The following method accepts a list of pickled histograms and | |
| 432 // builds a histogram and updates shadow copy of histogram data in the | |
| 433 // browser process. | |
| 434 static bool DeserializeHistogramInfo(const std::string& histogram_info); | |
| 435 | |
| 436 // This constant if for FindCorruption. Since snapshots of histograms are | 412 // This constant if for FindCorruption. Since snapshots of histograms are |
| 437 // taken asynchronously relative to sampling, and our counting code currently | 413 // taken asynchronously relative to sampling, and our counting code currently |
| 438 // does not prevent race conditions, it is pretty likely that we'll catch a | 414 // does not prevent race conditions, it is pretty likely that we'll catch a |
| 439 // redundant count that doesn't match the sample count. We allow for a | 415 // redundant count that doesn't match the sample count. We allow for a |
| 440 // certain amount of slop before flagging this as an inconsistency. Even with | 416 // certain amount of slop before flagging this as an inconsistency. Even with |
| 441 // an inconsistency, we'll snapshot it again (for UMA in about a half hour), | 417 // an inconsistency, we'll snapshot it again (for UMA in about a half hour), |
| 442 // so we'll eventually get the data, if it was not the result of a corruption. | 418 // so we'll eventually get the data, if it was not the result of a corruption. |
| 443 static const int kCommonRaceBasedCountMismatch; | 419 static const int kCommonRaceBasedCountMismatch; |
| 444 | 420 |
| 445 // Check to see if bucket ranges, counts and tallies in the snapshot are | 421 // Check to see if bucket ranges, counts and tallies in the snapshot are |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 469 Sample* maximum, | 445 Sample* maximum, |
| 470 size_t* bucket_count); | 446 size_t* bucket_count); |
| 471 | 447 |
| 472 // HistogramBase implementation: | 448 // HistogramBase implementation: |
| 473 virtual HistogramType GetHistogramType() const OVERRIDE; | 449 virtual HistogramType GetHistogramType() const OVERRIDE; |
| 474 virtual bool HasConstructionArguments(Sample minimum, | 450 virtual bool HasConstructionArguments(Sample minimum, |
| 475 Sample maximum, | 451 Sample maximum, |
| 476 size_t bucket_count) const OVERRIDE; | 452 size_t bucket_count) const OVERRIDE; |
| 477 virtual void Add(Sample value) OVERRIDE; | 453 virtual void Add(Sample value) OVERRIDE; |
| 478 virtual scoped_ptr<HistogramSamples> SnapshotSamples() const OVERRIDE; | 454 virtual scoped_ptr<HistogramSamples> SnapshotSamples() const OVERRIDE; |
| 455 virtual void AddSamples(const HistogramSamples& samples) OVERRIDE; | |
| 456 virtual bool AddSamplesFromPickle(PickleIterator* iter) OVERRIDE; | |
| 479 virtual void WriteHTMLGraph(std::string* output) const OVERRIDE; | 457 virtual void WriteHTMLGraph(std::string* output) const OVERRIDE; |
| 480 virtual void WriteAscii(std::string* output) const OVERRIDE; | 458 virtual void WriteAscii(std::string* output) const OVERRIDE; |
| 481 | 459 |
| 482 protected: | 460 protected: |
| 483 // |bucket_count| and |ranges| should contain the underflow and overflow | 461 // |bucket_count| and |ranges| should contain the underflow and overflow |
| 484 // buckets. See top comments for example. | 462 // buckets. See top comments for example. |
| 485 Histogram(const std::string& name, | 463 Histogram(const std::string& name, |
| 486 Sample minimum, | 464 Sample minimum, |
| 487 Sample maximum, | 465 Sample maximum, |
| 488 size_t bucket_count, | 466 size_t bucket_count, |
| 489 const BucketRanges* ranges); | 467 const BucketRanges* ranges); |
| 490 | 468 |
| 491 virtual ~Histogram(); | 469 virtual ~Histogram(); |
| 492 | 470 |
| 493 // Serialize the histogram's ranges to |*pickle|, returning true on success. | 471 // HistogramBase implementation: |
| 494 // Most subclasses can leave this no-op implementation, but some will want to | 472 virtual bool SerializeInfoImpl(Pickle* pickle) const OVERRIDE; |
| 495 // override it, especially if the ranges cannot be re-derived from other | |
| 496 // serialized parameters. | |
| 497 virtual bool SerializeRanges(Pickle* pickle) const; | |
| 498 | 473 |
| 499 // Method to override to skip the display of the i'th bucket if it's empty. | 474 // Method to override to skip the display of the i'th bucket if it's empty. |
| 500 virtual bool PrintEmptyBucket(size_t index) const; | 475 virtual bool PrintEmptyBucket(size_t index) const; |
| 501 | 476 |
| 502 // Get normalized size, relative to the ranges(i). | 477 // Get normalized size, relative to the ranges(i). |
| 503 virtual double GetBucketSize(Count current, size_t i) const; | 478 virtual double GetBucketSize(Count current, size_t i) const; |
| 504 | 479 |
| 505 // Return a string description of what goes in a given bucket. | 480 // Return a string description of what goes in a given bucket. |
| 506 // Most commonly this is the numeric value, but in derived classes it may | 481 // Most commonly this is the numeric value, but in derived classes it may |
| 507 // be a name (or string description) given to the bucket. | 482 // be a name (or string description) given to the bucket. |
| 508 virtual const std::string GetAsciiBucketRange(size_t it) const; | 483 virtual const std::string GetAsciiBucketRange(size_t it) const; |
| 509 | 484 |
| 510 private: | 485 private: |
| 511 // Allow tests to corrupt our innards for testing purposes. | 486 // Allow tests to corrupt our innards for testing purposes. |
| 512 FRIEND_TEST_ALL_PREFIXES(HistogramTest, BoundsTest); | 487 FRIEND_TEST_ALL_PREFIXES(HistogramTest, BoundsTest); |
| 513 FRIEND_TEST_ALL_PREFIXES(HistogramTest, BucketPlacementTest); | 488 FRIEND_TEST_ALL_PREFIXES(HistogramTest, BucketPlacementTest); |
| 514 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptBucketBounds); | 489 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptBucketBounds); |
| 515 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts); | 490 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts); |
| 516 FRIEND_TEST_ALL_PREFIXES(HistogramTest, NameMatchTest); | 491 FRIEND_TEST_ALL_PREFIXES(HistogramTest, NameMatchTest); |
| 517 | 492 |
| 518 friend class StatisticsRecorder; // To allow it to delete duplicates. | 493 friend class StatisticsRecorder; // To allow it to delete duplicates. |
| 519 friend class StatisticsRecorderTest; | 494 friend class StatisticsRecorderTest; |
| 495 friend HistogramBase* HistogramBase::DeserializeHistogramInfo( | |
| 496 PickleIterator* iter); | |
|
Ilya Sherman
2012/12/29 00:17:30
Why does HistogramBase need to know about the Hist
kaiwang
2013/01/08 00:51:40
I need a function to know all kind of histograms t
Ilya Sherman
2013/01/08 22:31:53
If you keep roughly the current design, I'd prefer
| |
| 497 | |
| 498 static HistogramBase* DeserializeHistogramInfo(PickleIterator* iter); | |
| 520 | 499 |
| 521 // Implementation of SnapshotSamples function. | 500 // Implementation of SnapshotSamples function. |
| 522 scoped_ptr<SampleVector> SnapshotSampleVector() const; | 501 scoped_ptr<SampleVector> SnapshotSampleVector() const; |
| 523 | 502 |
| 524 //---------------------------------------------------------------------------- | 503 //---------------------------------------------------------------------------- |
| 525 // Helpers for emitting Ascii graphic. Each method appends data to output. | 504 // Helpers for emitting Ascii graphic. Each method appends data to output. |
| 526 | 505 |
| 527 void WriteAsciiImpl(bool graph_it, | 506 void WriteAsciiImpl(bool graph_it, |
| 528 const std::string& newline, | 507 const std::string& newline, |
| 529 std::string* output) const; | 508 std::string* output) const; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 TimeDelta minimum, | 569 TimeDelta minimum, |
| 591 TimeDelta maximum, | 570 TimeDelta maximum, |
| 592 size_t bucket_count, | 571 size_t bucket_count, |
| 593 int32 flags); | 572 int32 flags); |
| 594 | 573 |
| 595 // Create a LinearHistogram and store a list of number/text values for use in | 574 // Create a LinearHistogram and store a list of number/text values for use in |
| 596 // writing the histogram graph. | 575 // writing the histogram graph. |
| 597 // |descriptions| can be NULL, which means no special descriptions to set. If | 576 // |descriptions| can be NULL, which means no special descriptions to set. If |
| 598 // it's not NULL, the last element in the array must has a NULL in its | 577 // it's not NULL, the last element in the array must has a NULL in its |
| 599 // "description" field. | 578 // "description" field. |
| 579 struct DescriptionPair { | |
| 580 Sample sample; | |
| 581 const char* description; // Null means end of a list of pairs. | |
| 582 }; | |
|
Ilya Sherman
2012/12/29 00:17:30
nit: Please move this to be above the comment that
kaiwang
2013/01/08 00:51:40
Done.
| |
| 600 static Histogram* FactoryGetWithRangeDescription( | 583 static Histogram* FactoryGetWithRangeDescription( |
| 601 const std::string& name, | 584 const std::string& name, |
| 602 Sample minimum, | 585 Sample minimum, |
| 603 Sample maximum, | 586 Sample maximum, |
| 604 size_t bucket_count, | 587 size_t bucket_count, |
| 605 int32 flags, | 588 int32 flags, |
| 606 const DescriptionPair descriptions[]); | 589 const DescriptionPair descriptions[]); |
| 607 | 590 |
| 608 static void InitializeBucketRanges(Sample minimum, | 591 static void InitializeBucketRanges(Sample minimum, |
| 609 Sample maximum, | 592 Sample maximum, |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 624 | 607 |
| 625 // If we have a description for a bucket, then return that. Otherwise | 608 // If we have a description for a bucket, then return that. Otherwise |
| 626 // let parent class provide a (numeric) description. | 609 // let parent class provide a (numeric) description. |
| 627 virtual const std::string GetAsciiBucketRange(size_t i) const OVERRIDE; | 610 virtual const std::string GetAsciiBucketRange(size_t i) const OVERRIDE; |
| 628 | 611 |
| 629 // Skip printing of name for numeric range if we have a name (and if this is | 612 // Skip printing of name for numeric range if we have a name (and if this is |
| 630 // an empty bucket). | 613 // an empty bucket). |
| 631 virtual bool PrintEmptyBucket(size_t index) const OVERRIDE; | 614 virtual bool PrintEmptyBucket(size_t index) const OVERRIDE; |
| 632 | 615 |
| 633 private: | 616 private: |
| 617 friend HistogramBase* HistogramBase::DeserializeHistogramInfo( | |
| 618 PickleIterator* iter); | |
| 619 static HistogramBase* DeserializeHistogramInfo(PickleIterator* iter); | |
| 620 | |
| 634 // For some ranges, we store a printable description of a bucket range. | 621 // For some ranges, we store a printable description of a bucket range. |
| 635 // If there is no desciption, then GetAsciiBucketRange() uses parent class | 622 // If there is no desciption, then GetAsciiBucketRange() uses parent class |
| 636 // to provide a description. | 623 // to provide a description. |
| 637 typedef std::map<Sample, std::string> BucketDescriptionMap; | 624 typedef std::map<Sample, std::string> BucketDescriptionMap; |
| 638 BucketDescriptionMap bucket_description_; | 625 BucketDescriptionMap bucket_description_; |
| 639 | 626 |
| 640 DISALLOW_COPY_AND_ASSIGN(LinearHistogram); | 627 DISALLOW_COPY_AND_ASSIGN(LinearHistogram); |
| 641 }; | 628 }; |
| 642 | 629 |
| 643 //------------------------------------------------------------------------------ | 630 //------------------------------------------------------------------------------ |
| 644 | 631 |
| 645 // BooleanHistogram is a histogram for booleans. | 632 // BooleanHistogram is a histogram for booleans. |
| 646 class BASE_EXPORT BooleanHistogram : public LinearHistogram { | 633 class BASE_EXPORT BooleanHistogram : public LinearHistogram { |
| 647 public: | 634 public: |
| 648 static Histogram* FactoryGet(const std::string& name, int32 flags); | 635 static Histogram* FactoryGet(const std::string& name, int32 flags); |
| 649 | 636 |
| 650 virtual HistogramType GetHistogramType() const OVERRIDE; | 637 virtual HistogramType GetHistogramType() const OVERRIDE; |
| 651 | 638 |
| 652 virtual void AddBoolean(bool value) OVERRIDE; | 639 virtual void AddBoolean(bool value) OVERRIDE; |
| 653 | 640 |
| 654 private: | 641 private: |
| 655 BooleanHistogram(const std::string& name, const BucketRanges* ranges); | 642 BooleanHistogram(const std::string& name, const BucketRanges* ranges); |
| 656 | 643 |
| 644 friend HistogramBase* HistogramBase::DeserializeHistogramInfo( | |
| 645 PickleIterator* iter); | |
| 646 static HistogramBase* DeserializeHistogramInfo(PickleIterator* iter); | |
| 647 | |
| 657 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram); | 648 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram); |
| 658 }; | 649 }; |
| 659 | 650 |
| 660 //------------------------------------------------------------------------------ | 651 //------------------------------------------------------------------------------ |
| 661 | 652 |
| 662 // CustomHistogram is a histogram for a set of custom integers. | 653 // CustomHistogram is a histogram for a set of custom integers. |
| 663 class BASE_EXPORT CustomHistogram : public Histogram { | 654 class BASE_EXPORT CustomHistogram : public Histogram { |
| 664 public: | 655 public: |
| 665 // |custom_ranges| contains a vector of limits on ranges. Each limit should be | 656 // |custom_ranges| contains a vector of limits on ranges. Each limit should be |
| 666 // > 0 and < kSampleType_MAX. (Currently 0 is still accepted for backward | 657 // > 0 and < kSampleType_MAX. (Currently 0 is still accepted for backward |
| 667 // compatibility). The limits can be unordered or contain duplication, but | 658 // compatibility). The limits can be unordered or contain duplication, but |
| 668 // client should not depend on this. | 659 // client should not depend on this. |
| 669 static Histogram* FactoryGet(const std::string& name, | 660 static Histogram* FactoryGet(const std::string& name, |
| 670 const std::vector<Sample>& custom_ranges, | 661 const std::vector<Sample>& custom_ranges, |
| 671 int32 flags); | 662 int32 flags); |
| 672 | 663 |
| 673 // Overridden from Histogram: | 664 // Overridden from Histogram: |
| 674 virtual HistogramType GetHistogramType() const OVERRIDE; | 665 virtual HistogramType GetHistogramType() const OVERRIDE; |
| 675 | 666 |
| 676 // Helper method for transforming an array of valid enumeration values | 667 // Helper method for transforming an array of valid enumeration values |
| 677 // to the std::vector<int> expected by HISTOGRAM_CUSTOM_ENUMERATION. | 668 // to the std::vector<int> expected by HISTOGRAM_CUSTOM_ENUMERATION. |
| 678 // This function ensures that a guard bucket exists right after any | 669 // This function ensures that a guard bucket exists right after any |
| 679 // valid sample value (unless the next higher sample is also a valid value), | 670 // valid sample value (unless the next higher sample is also a valid value), |
| 680 // so that invalid samples never fall into the same bucket as valid samples. | 671 // so that invalid samples never fall into the same bucket as valid samples. |
| 681 // TODO(kaiwang): Change name to ArrayToCustomEnumRanges. | 672 // TODO(kaiwang): Change name to ArrayToCustomEnumRanges. |
| 682 static std::vector<Sample> ArrayToCustomRanges(const Sample* values, | 673 static std::vector<Sample> ArrayToCustomRanges(const Sample* values, |
| 683 size_t num_values); | 674 size_t num_values); |
| 684 | |
| 685 // Helper for deserializing CustomHistograms. |*ranges| should already be | |
| 686 // correctly sized before this call. Return true on success. | |
| 687 static bool DeserializeRanges(PickleIterator* iter, | |
| 688 std::vector<Sample>* ranges); | |
| 689 protected: | 675 protected: |
| 690 CustomHistogram(const std::string& name, | 676 CustomHistogram(const std::string& name, |
| 691 const BucketRanges* ranges); | 677 const BucketRanges* ranges); |
| 692 | 678 |
| 693 virtual bool SerializeRanges(Pickle* pickle) const OVERRIDE; | 679 // HistogramBase implementation: |
| 680 virtual bool SerializeInfoImpl(Pickle* pickle) const OVERRIDE; | |
| 694 | 681 |
| 695 virtual double GetBucketSize(Count current, size_t i) const OVERRIDE; | 682 virtual double GetBucketSize(Count current, size_t i) const OVERRIDE; |
| 696 | 683 |
| 697 private: | 684 private: |
| 685 friend HistogramBase* HistogramBase::DeserializeHistogramInfo( | |
| 686 PickleIterator* iter); | |
| 687 static HistogramBase* DeserializeHistogramInfo(PickleIterator* iter); | |
| 688 | |
| 698 static bool ValidateCustomRanges(const std::vector<Sample>& custom_ranges); | 689 static bool ValidateCustomRanges(const std::vector<Sample>& custom_ranges); |
| 699 static BucketRanges* CreateBucketRangesFromCustomRanges( | 690 static BucketRanges* CreateBucketRangesFromCustomRanges( |
| 700 const std::vector<Sample>& custom_ranges); | 691 const std::vector<Sample>& custom_ranges); |
| 701 | 692 |
| 702 DISALLOW_COPY_AND_ASSIGN(CustomHistogram); | 693 DISALLOW_COPY_AND_ASSIGN(CustomHistogram); |
| 703 }; | 694 }; |
| 704 | 695 |
| 705 } // namespace base | 696 } // namespace base |
| 706 | 697 |
| 707 #endif // BASE_METRICS_HISTOGRAM_H_ | 698 #endif // BASE_METRICS_HISTOGRAM_H_ |
| OLD | NEW |