| 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. |
| 11 | 11 |
| 12 // The default layout of buckets is exponential. For example, buckets might | 12 // For Histogram(exponential histogram), LinearHistogram and CustomHistogram, |
| 13 // contain (sequentially) the count of values in the following intervals: | 13 // the minimum for a declared range is 1 (instead of 0), while the maximum is |
| 14 // (HistogramBase::kSampleType_MAX - 1). Currently you can declare histograms |
| 15 // with ranges exceeding those limits (e.g. 0 as minimal or |
| 16 // HistogramBase::kSampleType_MAX as maximal), but those excesses will be |
| 17 // silently clamped to those limits (for backwards compatibility with existing |
| 18 // code). Best practice is to not exceed the limits. |
| 19 |
| 20 // For Histogram and LinearHistogram, the maximum for a declared range should |
| 21 // always be larger (not equal) than minmal range. Zero and |
| 22 // HistogramBase::kSampleType_MAX are implicitly added as first and last ranges, |
| 23 // so the smallest legal bucket_count is 3. However CustomHistogram can have |
| 24 // bucket count as 2 (when you give a custom ranges vector containing only 1 |
| 25 // range). |
| 26 // For these 3 kinds of histograms, the max bucket count is always |
| 27 // (Histogram::kBucketCount_MAX - 1). |
| 28 |
| 29 // The buckets layout of class Histogram is exponential. For example, buckets |
| 30 // might contain (sequentially) the count of values in the following intervals: |
| 14 // [0,1), [1,2), [2,4), [4,8), [8,16), [16,32), [32,64), [64,infinity) | 31 // [0,1), [1,2), [2,4), [4,8), [8,16), [16,32), [32,64), [64,infinity) |
| 15 // That bucket allocation would actually result from construction of a histogram | 32 // That bucket allocation would actually result from construction of a histogram |
| 16 // for values between 1 and 64, with 8 buckets, such as: | 33 // for values between 1 and 64, with 8 buckets, such as: |
| 17 // Histogram count(L"some name", 1, 64, 8); | 34 // Histogram count("some name", 1, 64, 8); |
| 18 // Note that the underflow bucket [0,1) and the overflow bucket [64,infinity) | 35 // Note that the underflow bucket [0,1) and the overflow bucket [64,infinity) |
| 19 // are not counted by the constructor in the user supplied "bucket_count" | 36 // are also counted by the constructor in the user supplied "bucket_count" |
| 20 // argument. | 37 // argument. |
| 21 // The above example has an exponential ratio of 2 (doubling the bucket width | 38 // The above example has an exponential ratio of 2 (doubling the bucket width |
| 22 // in each consecutive bucket. The Histogram class automatically calculates | 39 // in each consecutive bucket. The Histogram class automatically calculates |
| 23 // the smallest ratio that it can use to construct the number of buckets | 40 // the smallest ratio that it can use to construct the number of buckets |
| 24 // selected in the constructor. An another example, if you had 50 buckets, | 41 // selected in the constructor. An another example, if you had 50 buckets, |
| 25 // and millisecond time values from 1 to 10000, then the ratio between | 42 // and millisecond time values from 1 to 10000, then the ratio between |
| 26 // consecutive bucket widths will be approximately somewhere around the 50th | 43 // consecutive bucket widths will be approximately somewhere around the 50th |
| 27 // root of 10000. This approach provides very fine grain (narrow) buckets | 44 // root of 10000. This approach provides very fine grain (narrow) buckets |
| 28 // at the low end of the histogram scale, but allows the histogram to cover a | 45 // at the low end of the histogram scale, but allows the histogram to cover a |
| 29 // gigantic range with the addition of very few buckets. | 46 // gigantic range with the addition of very few buckets. |
| 30 | 47 |
| 31 // Histograms use a pattern involving a function static variable, that is a | 48 // Usually we use macros to define and use a histogram. These macros use a |
| 32 // pointer to a histogram. This static is explicitly initialized on any thread | 49 // pattern involving a function static variable, that is a pointer to a |
| 50 // histogram. This static is explicitly initialized on any thread |
| 33 // that detects a uninitialized (NULL) pointer. The potentially racy | 51 // that detects a uninitialized (NULL) pointer. The potentially racy |
| 34 // initialization is not a problem as it is always set to point to the same | 52 // initialization is not a problem as it is always set to point to the same |
| 35 // value (i.e., the FactoryGet always returns the same value). FactoryGet | 53 // value (i.e., the FactoryGet always returns the same value). FactoryGet |
| 36 // is also completely thread safe, which results in a completely thread safe, | 54 // is also completely thread safe, which results in a completely thread safe, |
| 37 // and relatively fast, set of counters. To avoid races at shutdown, the static | 55 // and relatively fast, set of counters. To avoid races at shutdown, the static |
| 38 // pointer is NOT deleted, and we leak the histograms at process termination. | 56 // pointer is NOT deleted, and we leak the histograms at process termination. |
| 39 | 57 |
| 40 #ifndef BASE_METRICS_HISTOGRAM_H_ | 58 #ifndef BASE_METRICS_HISTOGRAM_H_ |
| 41 #define BASE_METRICS_HISTOGRAM_H_ | 59 #define BASE_METRICS_HISTOGRAM_H_ |
| 42 | 60 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 // problems down the line if you add additional buckets to the histogram. Note | 188 // problems down the line if you add additional buckets to the histogram. Note |
| 171 // also that, despite explicitly setting the minimum bucket value to |1| below, | 189 // also that, despite explicitly setting the minimum bucket value to |1| below, |
| 172 // it is fine for enumerated histograms to be 0-indexed -- this is because | 190 // it is fine for enumerated histograms to be 0-indexed -- this is because |
| 173 // enumerated histograms should never have underflow. | 191 // enumerated histograms should never have underflow. |
| 174 #define HISTOGRAM_ENUMERATION(name, sample, boundary_value) \ | 192 #define HISTOGRAM_ENUMERATION(name, sample, boundary_value) \ |
| 175 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ | 193 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ |
| 176 base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ | 194 base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ |
| 177 boundary_value + 1, base::Histogram::kNoFlags)) | 195 boundary_value + 1, base::Histogram::kNoFlags)) |
| 178 | 196 |
| 179 // Support histograming of an enumerated value. Samples should be one of the | 197 // Support histograming of an enumerated value. Samples should be one of the |
| 180 // std::vector<int> list provided via |custom_ranges|. You can use the helper | 198 // std::vector<int> list provided via |custom_ranges|. See comments above |
| 181 // function |base::CustomHistogram::ArrayToCustomRanges(samples, num_samples)| | 199 // CustomRanges::FactoryGet about the requirement of |custom_ranges|. |
| 182 // to transform a C-style array of valid sample values to a std::vector<int>. | 200 // You can use the helper function CustomHistogram::ArrayToCustomRanges to |
| 201 // transform a C-style array of valid sample values to a std::vector<int>. |
| 183 #define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \ | 202 #define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \ |
| 184 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ | 203 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ |
| 185 base::CustomHistogram::FactoryGet(name, custom_ranges, \ | 204 base::CustomHistogram::FactoryGet(name, custom_ranges, \ |
| 186 base::Histogram::kNoFlags)) | 205 base::Histogram::kNoFlags)) |
| 187 | 206 |
| 188 //------------------------------------------------------------------------------ | 207 //------------------------------------------------------------------------------ |
| 189 // Define Debug vs non-debug flavors of macros. | 208 // Define Debug vs non-debug flavors of macros. |
| 190 #ifndef NDEBUG | 209 #ifndef NDEBUG |
| 191 | 210 |
| 192 #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample) | 211 #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample) |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 | 350 |
| 332 typedef std::vector<Count> Counts; | 351 typedef std::vector<Count> Counts; |
| 333 | 352 |
| 334 // These enums are used to facilitate deserialization of renderer histograms | 353 // These enums are used to facilitate deserialization of renderer histograms |
| 335 // into the browser. | 354 // into the browser. |
| 336 enum ClassType { | 355 enum ClassType { |
| 337 HISTOGRAM, | 356 HISTOGRAM, |
| 338 LINEAR_HISTOGRAM, | 357 LINEAR_HISTOGRAM, |
| 339 BOOLEAN_HISTOGRAM, | 358 BOOLEAN_HISTOGRAM, |
| 340 CUSTOM_HISTOGRAM, | 359 CUSTOM_HISTOGRAM, |
| 341 NOT_VALID_IN_RENDERER | 360 NOT_VALID_IN_RENDERER, |
| 342 }; | 361 }; |
| 343 | 362 |
| 344 enum BucketLayout { | 363 enum BucketLayout { |
| 345 EXPONENTIAL, | 364 EXPONENTIAL, |
| 346 LINEAR, | 365 LINEAR, |
| 347 CUSTOM | 366 CUSTOM, |
| 348 }; | 367 }; |
| 349 | 368 |
| 350 enum Flags { | 369 enum Flags { |
| 351 kNoFlags = 0, | 370 kNoFlags = 0, |
| 352 kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded. | 371 kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded. |
| 353 | 372 |
| 354 // Indicate that the histogram was pickled to be sent across an IPC Channel. | 373 // Indicate that the histogram was pickled to be sent across an IPC Channel. |
| 355 // If we observe this flag on a histogram being aggregated into after IPC, | 374 // If we observe this flag on a histogram being aggregated into after IPC, |
| 356 // then we are running in a single process mode, and the aggregation should | 375 // then we are running in a single process mode, and the aggregation should |
| 357 // not take place (as we would be aggregating back into the source | 376 // not take place (as we would be aggregating back into the source |
| (...skipping 16 matching lines...) Expand all Loading... |
| 374 struct DescriptionPair { | 393 struct DescriptionPair { |
| 375 Sample sample; | 394 Sample sample; |
| 376 const char* description; // Null means end of a list of pairs. | 395 const char* description; // Null means end of a list of pairs. |
| 377 }; | 396 }; |
| 378 | 397 |
| 379 //---------------------------------------------------------------------------- | 398 //---------------------------------------------------------------------------- |
| 380 // Statistic values, developed over the life of the histogram. | 399 // Statistic values, developed over the life of the histogram. |
| 381 | 400 |
| 382 class BASE_EXPORT SampleSet { | 401 class BASE_EXPORT SampleSet { |
| 383 public: | 402 public: |
| 384 explicit SampleSet(); | 403 explicit SampleSet(size_t size); |
| 404 SampleSet(); |
| 385 ~SampleSet(); | 405 ~SampleSet(); |
| 386 | 406 |
| 387 // Adjust size of counts_ for use with given histogram. | 407 void Resize(size_t size); |
| 388 void Resize(const Histogram& histogram); | |
| 389 void CheckSize(const Histogram& histogram) const; | |
| 390 | 408 |
| 391 // Accessor for histogram to make routine additions. | 409 // Accessor for histogram to make routine additions. |
| 392 void Accumulate(Sample value, Count count, size_t index); | 410 void Accumulate(Sample value, Count count, size_t index); |
| 393 | 411 |
| 394 // Accessor methods. | 412 // Accessor methods. |
| 413 size_t size() const { return counts_.size(); } |
| 395 Count counts(size_t i) const { return counts_[i]; } | 414 Count counts(size_t i) const { return counts_[i]; } |
| 396 Count TotalCount() const; | 415 Count TotalCount() const; |
| 397 int64 sum() const { return sum_; } | 416 int64 sum() const { return sum_; } |
| 398 int64 redundant_count() const { return redundant_count_; } | 417 int64 redundant_count() const { return redundant_count_; } |
| 399 | 418 |
| 400 // Arithmetic manipulation of corresponding elements of the set. | 419 // Arithmetic manipulation of corresponding elements of the set. |
| 401 void Add(const SampleSet& other); | 420 void Add(const SampleSet& other); |
| 402 void Subtract(const SampleSet& other); | 421 void Subtract(const SampleSet& other); |
| 403 | 422 |
| 404 bool Serialize(Pickle* pickle) const; | 423 bool Serialize(Pickle* pickle) const; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 static Histogram* FactoryGet(const std::string& name, | 459 static Histogram* FactoryGet(const std::string& name, |
| 441 Sample minimum, | 460 Sample minimum, |
| 442 Sample maximum, | 461 Sample maximum, |
| 443 size_t bucket_count, | 462 size_t bucket_count, |
| 444 Flags flags); | 463 Flags flags); |
| 445 static Histogram* FactoryTimeGet(const std::string& name, | 464 static Histogram* FactoryTimeGet(const std::string& name, |
| 446 base::TimeDelta minimum, | 465 base::TimeDelta minimum, |
| 447 base::TimeDelta maximum, | 466 base::TimeDelta maximum, |
| 448 size_t bucket_count, | 467 size_t bucket_count, |
| 449 Flags flags); | 468 Flags flags); |
| 469 |
| 450 // Time call for use with DHISTOGRAM*. | 470 // Time call for use with DHISTOGRAM*. |
| 451 // Returns TimeTicks::Now() in debug and TimeTicks() in release build. | 471 // Returns TimeTicks::Now() in debug and TimeTicks() in release build. |
| 452 static TimeTicks DebugNow(); | 472 static TimeTicks DebugNow(); |
| 453 | 473 |
| 474 static void InitializeBucketRanges(Sample minimum, |
| 475 Sample maximum, |
| 476 size_t bucket_count, |
| 477 BucketRanges* ranges); |
| 478 |
| 454 virtual void Add(Sample value) OVERRIDE; | 479 virtual void Add(Sample value) OVERRIDE; |
| 455 | 480 |
| 456 // This method is an interface, used only by BooleanHistogram. | 481 // This method is an interface, used only by BooleanHistogram. |
| 457 virtual void AddBoolean(bool value); | 482 virtual void AddBoolean(bool value); |
| 458 | 483 |
| 459 // Accept a TimeDelta to increment. | 484 // Accept a TimeDelta to increment. |
| 460 void AddTime(TimeDelta time) { | 485 void AddTime(TimeDelta time) { |
| 461 Add(static_cast<int>(time.InMilliseconds())); | 486 Add(static_cast<int>(time.InMilliseconds())); |
| 462 } | 487 } |
| 463 | 488 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 // have memory over-writes, or DRAM failures). | 525 // have memory over-writes, or DRAM failures). |
| 501 virtual Inconsistencies FindCorruption(const SampleSet& snapshot) const; | 526 virtual Inconsistencies FindCorruption(const SampleSet& snapshot) const; |
| 502 | 527 |
| 503 //---------------------------------------------------------------------------- | 528 //---------------------------------------------------------------------------- |
| 504 // Accessors for factory constuction, serialization and testing. | 529 // Accessors for factory constuction, serialization and testing. |
| 505 //---------------------------------------------------------------------------- | 530 //---------------------------------------------------------------------------- |
| 506 virtual ClassType histogram_type() const; | 531 virtual ClassType histogram_type() const; |
| 507 Sample declared_min() const { return declared_min_; } | 532 Sample declared_min() const { return declared_min_; } |
| 508 Sample declared_max() const { return declared_max_; } | 533 Sample declared_max() const { return declared_max_; } |
| 509 virtual Sample ranges(size_t i) const; | 534 virtual Sample ranges(size_t i) const; |
| 510 uint32 range_checksum() const { return range_checksum_; } | |
| 511 virtual size_t bucket_count() const; | 535 virtual size_t bucket_count() const; |
| 512 BucketRanges* bucket_ranges() const { return bucket_ranges_; } | 536 const BucketRanges* bucket_ranges() const { return bucket_ranges_; } |
| 513 void set_bucket_ranges(BucketRanges* bucket_ranges) { | 537 |
| 514 bucket_ranges_ = bucket_ranges; | |
| 515 } | |
| 516 // Snapshot the current complete set of sample data. | 538 // Snapshot the current complete set of sample data. |
| 517 // Override with atomic/locked snapshot if needed. | 539 // Override with atomic/locked snapshot if needed. |
| 518 virtual void SnapshotSample(SampleSet* sample) const; | 540 virtual void SnapshotSample(SampleSet* sample) const; |
| 519 | 541 |
| 520 virtual bool HasConstructorArguments(Sample minimum, Sample maximum, | 542 virtual bool HasConstructionArguments(Sample minimum, |
| 521 size_t bucket_count); | 543 Sample maximum, |
| 522 | 544 size_t bucket_count); |
| 523 virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum, | |
| 524 TimeDelta maximum, | |
| 525 size_t bucket_count); | |
| 526 // Return true iff the range_checksum_ matches current |ranges_| vector in | |
| 527 // |bucket_ranges_|. | |
| 528 bool HasValidRangeChecksum() const; | |
| 529 | |
| 530 protected: | 545 protected: |
| 531 Histogram(const std::string& name, Sample minimum, | 546 // |bucket_count| and |ranges| should contain the underflow and overflow |
| 532 Sample maximum, size_t bucket_count); | 547 // buckets. See top comments for example. |
| 533 Histogram(const std::string& name, TimeDelta minimum, | 548 Histogram(const std::string& name, |
| 534 TimeDelta maximum, size_t bucket_count); | 549 Sample minimum, |
| 550 Sample maximum, |
| 551 size_t bucket_count, |
| 552 const BucketRanges* ranges); |
| 535 | 553 |
| 536 virtual ~Histogram(); | 554 virtual ~Histogram(); |
| 537 | 555 |
| 556 // This function validates histogram construction arguments. It returns false |
| 557 // if some of the arguments are totally bad. |
| 558 // Note. Currently it allow some bad input, e.g. 0 as minimum, but silently |
| 559 // converts it to good input: 1. |
| 560 // TODO(kaiwang): Be more restrict and return false for any bad input, and |
| 561 // make this a readonly validating function. |
| 562 static bool InspectConstructionArguments(const std::string& name, |
| 563 Sample* minimum, |
| 564 Sample* maximum, |
| 565 size_t* bucket_count); |
| 566 |
| 538 // Serialize the histogram's ranges to |*pickle|, returning true on success. | 567 // 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 | 568 // 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 | 569 // override it, especially if the ranges cannot be re-derived from other |
| 541 // serialized parameters. | 570 // serialized parameters. |
| 542 virtual bool SerializeRanges(Pickle* pickle) const; | 571 virtual bool SerializeRanges(Pickle* pickle) const; |
| 543 | 572 |
| 544 // Initialize ranges_ mapping in bucket_ranges_. | |
| 545 void InitializeBucketRange(); | |
| 546 | |
| 547 // Method to override to skip the display of the i'th bucket if it's empty. | 573 // Method to override to skip the display of the i'th bucket if it's empty. |
| 548 virtual bool PrintEmptyBucket(size_t index) const; | 574 virtual bool PrintEmptyBucket(size_t index) const; |
| 549 | 575 |
| 550 //---------------------------------------------------------------------------- | 576 //---------------------------------------------------------------------------- |
| 551 // Methods to override to create histogram with different bucket widths. | 577 // Methods to override to create histogram with different bucket widths. |
| 552 //---------------------------------------------------------------------------- | 578 //---------------------------------------------------------------------------- |
| 553 // Find bucket to increment for sample value. | 579 // Find bucket to increment for sample value. |
| 554 virtual size_t BucketIndex(Sample value) const; | 580 virtual size_t BucketIndex(Sample value) const; |
| 555 // Get normalized size, relative to the ranges(i). | 581 // Get normalized size, relative to the ranges(i). |
| 556 virtual double GetBucketSize(Count current, size_t i) const; | 582 virtual double GetBucketSize(Count current, size_t i) const; |
| 557 | 583 |
| 558 // Recalculate range_checksum_. | |
| 559 void ResetRangeChecksum(); | |
| 560 | |
| 561 // Return a string description of what goes in a given bucket. | 584 // Return a string description of what goes in a given bucket. |
| 562 // Most commonly this is the numeric value, but in derived classes it may | 585 // Most commonly this is the numeric value, but in derived classes it may |
| 563 // be a name (or string description) given to the bucket. | 586 // be a name (or string description) given to the bucket. |
| 564 virtual const std::string GetAsciiBucketRange(size_t it) const; | 587 virtual const std::string GetAsciiBucketRange(size_t it) const; |
| 565 | 588 |
| 566 //---------------------------------------------------------------------------- | 589 //---------------------------------------------------------------------------- |
| 567 // Methods to override to create thread safe histogram. | 590 // Methods to override to create thread safe histogram. |
| 568 //---------------------------------------------------------------------------- | 591 //---------------------------------------------------------------------------- |
| 569 // Update all our internal data, including histogram | 592 // Update all our internal data, including histogram |
| 570 virtual void Accumulate(Sample value, Count count, size_t index); | 593 virtual void Accumulate(Sample value, Count count, size_t index); |
| 571 | 594 |
| 572 //---------------------------------------------------------------------------- | |
| 573 // Accessors for derived classes. | |
| 574 //---------------------------------------------------------------------------- | |
| 575 void SetBucketRange(size_t i, Sample value); | |
| 576 | |
| 577 // Validate that ranges_ in bucket_ranges_ was created sensibly (top and | |
| 578 // bottom range values relate properly to the declared_min_ and | |
| 579 // declared_max_). | |
| 580 bool ValidateBucketRanges() const; | |
| 581 | |
| 582 virtual uint32 CalculateRangeChecksum() const; | |
| 583 | |
| 584 private: | 595 private: |
| 585 // Allow tests to corrupt our innards for testing purposes. | 596 // Allow tests to corrupt our innards for testing purposes. |
| 586 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptBucketBounds); | 597 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptBucketBounds); |
| 587 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts); | 598 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts); |
| 588 FRIEND_TEST_ALL_PREFIXES(HistogramTest, Crc32SampleHash); | 599 FRIEND_TEST_ALL_PREFIXES(HistogramTest, Crc32SampleHash); |
| 589 FRIEND_TEST_ALL_PREFIXES(HistogramTest, Crc32TableTest); | 600 FRIEND_TEST_ALL_PREFIXES(HistogramTest, Crc32TableTest); |
| 590 | 601 |
| 591 friend class StatisticsRecorder; // To allow it to delete duplicates. | 602 friend class StatisticsRecorder; // To allow it to delete duplicates. |
| 592 | 603 friend class StatisticsRecorderTest; |
| 593 // Post constructor initialization. | |
| 594 void Initialize(); | |
| 595 | |
| 596 // Checksum function for accumulating range values into a checksum. | |
| 597 static uint32 Crc32(uint32 sum, Sample range); | |
| 598 | 604 |
| 599 //---------------------------------------------------------------------------- | 605 //---------------------------------------------------------------------------- |
| 600 // Helpers for emitting Ascii graphic. Each method appends data to output. | 606 // Helpers for emitting Ascii graphic. Each method appends data to output. |
| 601 | 607 |
| 602 void WriteAsciiImpl(bool graph_it, | 608 void WriteAsciiImpl(bool graph_it, |
| 603 const std::string& newline, | 609 const std::string& newline, |
| 604 std::string* output) const; | 610 std::string* output) const; |
| 605 | 611 |
| 606 // Find out how large the (graphically) the largest bucket will appear to be. | 612 // Find out how large the (graphically) the largest bucket will appear to be. |
| 607 double GetPeakBucketSize(const SampleSet& snapshot) const; | 613 double GetPeakBucketSize(const SampleSet& snapshot) const; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 618 | 624 |
| 619 // Write textual description of the bucket contents (relative to histogram). | 625 // Write textual description of the bucket contents (relative to histogram). |
| 620 // Output is the count in the buckets, as well as the percentage. | 626 // Output is the count in the buckets, as well as the percentage. |
| 621 void WriteAsciiBucketValue(Count current, double scaled_sum, | 627 void WriteAsciiBucketValue(Count current, double scaled_sum, |
| 622 std::string* output) const; | 628 std::string* output) const; |
| 623 | 629 |
| 624 // Produce actual graph (set of blank vs non blank char's) for a bucket. | 630 // Produce actual graph (set of blank vs non blank char's) for a bucket. |
| 625 void WriteAsciiBucketGraph(double current_size, double max_size, | 631 void WriteAsciiBucketGraph(double current_size, double max_size, |
| 626 std::string* output) const; | 632 std::string* output) const; |
| 627 | 633 |
| 628 //---------------------------------------------------------------------------- | 634 // Does not own this object. Should get from StatisticsRecorder. |
| 629 // Table for generating Crc32 values. | 635 const BucketRanges* bucket_ranges_; |
| 630 static const uint32 kCrcTable[256]; | |
| 631 //---------------------------------------------------------------------------- | |
| 632 // Invariant values set at/near construction time | |
| 633 | 636 |
| 634 Sample declared_min_; // Less than this goes into counts_[0] | 637 Sample declared_min_; // Less than this goes into counts_[0] |
| 635 Sample declared_max_; // Over this goes into counts_[bucket_count_ - 1]. | 638 Sample declared_max_; // Over this goes into counts_[bucket_count_ - 1]. |
| 636 size_t bucket_count_; // Dimension of counts_[]. | 639 size_t bucket_count_; // Dimension of counts_[]. |
| 637 | 640 |
| 638 // Flag the histogram for recording by UMA via metric_services.h. | 641 // Flag the histogram for recording by UMA via metric_services.h. |
| 639 Flags flags_; | 642 Flags flags_; |
| 640 | 643 |
| 641 // 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, | |
| 643 // containing kSampleType_MAX, to make calculations easy. | |
| 644 // The dimension of ranges_ in bucket_ranges_ is bucket_count + 1. | |
| 645 BucketRanges* bucket_ranges_; | |
| 646 | |
| 647 // 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 | |
| 649 // have been corrupted. | |
| 650 uint32 range_checksum_; | |
| 651 | |
| 652 // Finally, provide the state that changes with the addition of each new | 644 // Finally, provide the state that changes with the addition of each new |
| 653 // sample. | 645 // sample. |
| 654 SampleSet sample_; | 646 SampleSet sample_; |
| 655 | 647 |
| 656 DISALLOW_COPY_AND_ASSIGN(Histogram); | 648 DISALLOW_COPY_AND_ASSIGN(Histogram); |
| 657 }; | 649 }; |
| 658 | 650 |
| 659 //------------------------------------------------------------------------------ | 651 //------------------------------------------------------------------------------ |
| 660 | 652 |
| 661 // LinearHistogram is a more traditional histogram, with evenly spaced | 653 // LinearHistogram is a more traditional histogram, with evenly spaced |
| 662 // buckets. | 654 // buckets. |
| 663 class BASE_EXPORT LinearHistogram : public Histogram { | 655 class BASE_EXPORT LinearHistogram : public Histogram { |
| 664 public: | 656 public: |
| 665 virtual ~LinearHistogram(); | 657 virtual ~LinearHistogram(); |
| 666 | 658 |
| 667 /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit | 659 /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit |
| 668 default underflow bucket. */ | 660 default underflow bucket. */ |
| 669 static Histogram* FactoryGet(const std::string& name, | 661 static Histogram* FactoryGet(const std::string& name, |
| 670 Sample minimum, | 662 Sample minimum, |
| 671 Sample maximum, | 663 Sample maximum, |
| 672 size_t bucket_count, | 664 size_t bucket_count, |
| 673 Flags flags); | 665 Flags flags); |
| 674 static Histogram* FactoryTimeGet(const std::string& name, | 666 static Histogram* FactoryTimeGet(const std::string& name, |
| 675 TimeDelta minimum, | 667 TimeDelta minimum, |
| 676 TimeDelta maximum, | 668 TimeDelta maximum, |
| 677 size_t bucket_count, | 669 size_t bucket_count, |
| 678 Flags flags); | 670 Flags flags); |
| 679 | 671 |
| 672 static void InitializeBucketRanges(Sample minimum, |
| 673 Sample maximum, |
| 674 size_t bucket_count, |
| 675 BucketRanges* ranges); |
| 676 |
| 680 // Overridden from Histogram: | 677 // Overridden from Histogram: |
| 681 virtual ClassType histogram_type() const OVERRIDE; | 678 virtual ClassType histogram_type() const OVERRIDE; |
| 682 | 679 |
| 683 // Store a list of number/text values for use in rendering the histogram. | 680 // Store a list of number/text values for use in rendering the histogram. |
| 684 // The last element in the array has a null in its "description" slot. | 681 // The last element in the array has a null in its "description" slot. |
| 685 virtual void SetRangeDescriptions( | 682 virtual void SetRangeDescriptions( |
| 686 const DescriptionPair descriptions[]) OVERRIDE; | 683 const DescriptionPair descriptions[]) OVERRIDE; |
| 687 | 684 |
| 688 protected: | 685 protected: |
| 689 LinearHistogram(const std::string& name, Sample minimum, | 686 LinearHistogram(const std::string& name, |
| 690 Sample maximum, size_t bucket_count); | 687 Sample minimum, |
| 688 Sample maximum, |
| 689 size_t bucket_count, |
| 690 const BucketRanges* ranges); |
| 691 | 691 |
| 692 LinearHistogram(const std::string& name, TimeDelta minimum, | |
| 693 TimeDelta maximum, size_t bucket_count); | |
| 694 | |
| 695 // Initialize ranges_ mapping in bucket_ranges_. | |
| 696 void InitializeBucketRange(); | |
| 697 virtual double GetBucketSize(Count current, size_t i) const OVERRIDE; | 692 virtual double GetBucketSize(Count current, size_t i) const OVERRIDE; |
| 698 | 693 |
| 699 // If we have a description for a bucket, then return that. Otherwise | 694 // If we have a description for a bucket, then return that. Otherwise |
| 700 // let parent class provide a (numeric) description. | 695 // let parent class provide a (numeric) description. |
| 701 virtual const std::string GetAsciiBucketRange(size_t i) const OVERRIDE; | 696 virtual const std::string GetAsciiBucketRange(size_t i) const OVERRIDE; |
| 702 | 697 |
| 703 // Skip printing of name for numeric range if we have a name (and if this is | 698 // Skip printing of name for numeric range if we have a name (and if this is |
| 704 // an empty bucket). | 699 // an empty bucket). |
| 705 virtual bool PrintEmptyBucket(size_t index) const OVERRIDE; | 700 virtual bool PrintEmptyBucket(size_t index) const OVERRIDE; |
| 706 | 701 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 719 // BooleanHistogram is a histogram for booleans. | 714 // BooleanHistogram is a histogram for booleans. |
| 720 class BASE_EXPORT BooleanHistogram : public LinearHistogram { | 715 class BASE_EXPORT BooleanHistogram : public LinearHistogram { |
| 721 public: | 716 public: |
| 722 static Histogram* FactoryGet(const std::string& name, Flags flags); | 717 static Histogram* FactoryGet(const std::string& name, Flags flags); |
| 723 | 718 |
| 724 virtual ClassType histogram_type() const OVERRIDE; | 719 virtual ClassType histogram_type() const OVERRIDE; |
| 725 | 720 |
| 726 virtual void AddBoolean(bool value) OVERRIDE; | 721 virtual void AddBoolean(bool value) OVERRIDE; |
| 727 | 722 |
| 728 private: | 723 private: |
| 729 explicit BooleanHistogram(const std::string& name); | 724 BooleanHistogram(const std::string& name, const BucketRanges* ranges); |
| 730 | 725 |
| 731 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram); | 726 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram); |
| 732 }; | 727 }; |
| 733 | 728 |
| 734 //------------------------------------------------------------------------------ | 729 //------------------------------------------------------------------------------ |
| 735 | 730 |
| 736 // CustomHistogram is a histogram for a set of custom integers. | 731 // CustomHistogram is a histogram for a set of custom integers. |
| 737 class BASE_EXPORT CustomHistogram : public Histogram { | 732 class BASE_EXPORT CustomHistogram : public Histogram { |
| 738 public: | 733 public: |
| 739 | 734 // |custom_ranges| contains a vector of limits on ranges. Each limit should be |
| 735 // > 0 and < kSampleType_MAX. (Currently 0 is still accepted for backward |
| 736 // compatibility). The limits can be unordered or contain duplication, but |
| 737 // client should not depend on this. |
| 740 static Histogram* FactoryGet(const std::string& name, | 738 static Histogram* FactoryGet(const std::string& name, |
| 741 const std::vector<Sample>& custom_ranges, | 739 const std::vector<Sample>& custom_ranges, |
| 742 Flags flags); | 740 Flags flags); |
| 743 | 741 |
| 744 // Overridden from Histogram: | 742 // Overridden from Histogram: |
| 745 virtual ClassType histogram_type() const OVERRIDE; | 743 virtual ClassType histogram_type() const OVERRIDE; |
| 746 | 744 |
| 747 // Helper method for transforming an array of valid enumeration values | 745 // Helper method for transforming an array of valid enumeration values |
| 748 // to the std::vector<int> expected by HISTOGRAM_CUSTOM_ENUMERATION. | 746 // to the std::vector<int> expected by HISTOGRAM_CUSTOM_ENUMERATION. |
| 749 // This function ensures that a guard bucket exists right after any | 747 // This function ensures that a guard bucket exists right after any |
| 750 // valid sample value (unless the next higher sample is also a valid value), | 748 // valid sample value (unless the next higher sample is also a valid value), |
| 751 // so that invalid samples never fall into the same bucket as valid samples. | 749 // so that invalid samples never fall into the same bucket as valid samples. |
| 750 // TODO(kaiwang): Change name to ArrayToCustomEnumRanges. |
| 752 static std::vector<Sample> ArrayToCustomRanges(const Sample* values, | 751 static std::vector<Sample> ArrayToCustomRanges(const Sample* values, |
| 753 size_t num_values); | 752 size_t num_values); |
| 754 | 753 |
| 755 // Helper for deserializing CustomHistograms. |*ranges| should already be | 754 // Helper for deserializing CustomHistograms. |*ranges| should already be |
| 756 // correctly sized before this call. Return true on success. | 755 // correctly sized before this call. Return true on success. |
| 757 static bool DeserializeRanges(PickleIterator* iter, | 756 static bool DeserializeRanges(PickleIterator* iter, |
| 758 std::vector<Histogram::Sample>* ranges); | 757 std::vector<Sample>* ranges); |
| 759 | |
| 760 | |
| 761 protected: | 758 protected: |
| 762 CustomHistogram(const std::string& name, | 759 CustomHistogram(const std::string& name, |
| 763 const std::vector<Sample>& custom_ranges); | 760 const BucketRanges* ranges); |
| 764 | 761 |
| 765 virtual bool SerializeRanges(Pickle* pickle) const OVERRIDE; | 762 virtual bool SerializeRanges(Pickle* pickle) const OVERRIDE; |
| 766 | 763 |
| 767 // Initialize ranges_ mapping in bucket_ranges_. | |
| 768 void InitializedCustomBucketRange(const std::vector<Sample>& custom_ranges); | |
| 769 virtual double GetBucketSize(Count current, size_t i) const OVERRIDE; | 764 virtual double GetBucketSize(Count current, size_t i) const OVERRIDE; |
| 770 | 765 |
| 766 private: |
| 767 static bool ValidateCustomRanges(const std::vector<Sample>& custom_ranges); |
| 768 static BucketRanges* CreateBucketRangesFromCustomRanges( |
| 769 const std::vector<Sample>& custom_ranges); |
| 770 |
| 771 DISALLOW_COPY_AND_ASSIGN(CustomHistogram); | 771 DISALLOW_COPY_AND_ASSIGN(CustomHistogram); |
| 772 }; | 772 }; |
| 773 | 773 |
| 774 } // namespace base | 774 } // namespace base |
| 775 | 775 |
| 776 #endif // BASE_METRICS_HISTOGRAM_H_ | 776 #endif // BASE_METRICS_HISTOGRAM_H_ |
| OLD | NEW |