Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Side by Side Diff: base/metrics/histogram.h

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

Powered by Google App Engine
This is Rietveld 408576698