LCOV - code coverage report
Current view: top level - ipc/chromium/src/base - histogram.h (source / functions) Hit Total Coverage
Test: output.info Lines: 8 21 38.1 %
Date: 2017-07-14 16:53:18 Functions: 8 21 38.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : // Copyright (c) 2011 The Chromium Authors. All rights reserved.
       4             : // Use of this source code is governed by a BSD-style license that can be
       5             : // found in the LICENSE file.
       6             : 
       7             : // Histogram is an object that aggregates statistics, and can summarize them in
       8             : // various forms, including ASCII graphical, HTML, and numerically (as a
       9             : // vector of numbers corresponding to each of the aggregating buckets).
      10             : 
      11             : // It supports calls to accumulate either time intervals (which are processed
      12             : // as integral number of milliseconds), or arbitrary integral units.
      13             : 
      14             : // The default layout of buckets is exponential.  For example, buckets might
      15             : // contain (sequentially) the count of values in the following intervals:
      16             : // [0,1), [1,2), [2,4), [4,8), [8,16), [16,32), [32,64), [64,infinity)
      17             : // That bucket allocation would actually result from construction of a histogram
      18             : // for values between 1 and 64, with 8 buckets, such as:
      19             : // Histogram count(L"some name", 1, 64, 8);
      20             : // Note that the underflow bucket [0,1) and the overflow bucket [64,infinity)
      21             : // are not counted by the constructor in the user supplied "bucket_count"
      22             : // argument.
      23             : // The above example has an exponential ratio of 2 (doubling the bucket width
      24             : // in each consecutive bucket.  The Histogram class automatically calculates
      25             : // the smallest ratio that it can use to construct the number of buckets
      26             : // selected in the constructor.  An another example, if you had 50 buckets,
      27             : // and millisecond time values from 1 to 10000, then the ratio between
      28             : // consecutive bucket widths will be approximately somewhere around the 50th
      29             : // root of 10000.  This approach provides very fine grain (narrow) buckets
      30             : // at the low end of the histogram scale, but allows the histogram to cover a
      31             : // gigantic range with the addition of very few buckets.
      32             : 
      33             : // Histograms use a pattern involving a function static variable, that is a
      34             : // pointer to a histogram.  This static is explicitly initialized on any thread
      35             : // that detects a uninitialized (NULL) pointer.  The potentially racy
      36             : // initialization is not a problem as it is always set to point to the same
      37             : // value (i.e., the FactoryGet always returns the same value).  FactoryGet
      38             : // is also completely thread safe, which results in a completely thread safe,
      39             : // and relatively fast, set of counters.  To avoid races at shutdown, the static
      40             : // pointer is NOT deleted, and we leak the histograms at process termination.
      41             : 
      42             : #ifndef BASE_METRICS_HISTOGRAM_H_
      43             : #define BASE_METRICS_HISTOGRAM_H_
      44             : #pragma once
      45             : 
      46             : #include "mozilla/Atomics.h"
      47             : #include "mozilla/MemoryReporting.h"
      48             : 
      49             : #include <map>
      50             : #include <string>
      51             : #include <vector>
      52             : 
      53             : #include "base/time.h"
      54             : #include "base/lock.h"
      55             : 
      56             : namespace base {
      57             : 
      58             : //------------------------------------------------------------------------------
      59             : // Provide easy general purpose histogram in a macro, just like stats counters.
      60             : // The first four macros use 50 buckets.
      61             : 
      62             : #define HISTOGRAM_TIMES(name, sample) HISTOGRAM_CUSTOM_TIMES( \
      63             :     name, sample, base::TimeDelta::FromMilliseconds(1), \
      64             :     base::TimeDelta::FromSeconds(10), 50)
      65             : 
      66             : #define HISTOGRAM_COUNTS(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
      67             :     name, sample, 1, 1000000, 50)
      68             : 
      69             : #define HISTOGRAM_COUNTS_100(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
      70             :     name, sample, 1, 100, 50)
      71             : 
      72             : #define HISTOGRAM_COUNTS_10000(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
      73             :     name, sample, 1, 10000, 50)
      74             : 
      75             : #define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \
      76             :     static base::Histogram* counter(NULL); \
      77             :     if (!counter) \
      78             :       counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \
      79             :                                             base::Histogram::kNoFlags); \
      80             :     DCHECK_EQ(name, counter->histogram_name()); \
      81             :     counter->Add(sample); \
      82             :   } while (0)
      83             : 
      84             : #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
      85             :     HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
      86             : 
      87             : // For folks that need real specific times, use this to select a precise range
      88             : // of times you want plotted, and the number of buckets you want used.
      89             : #define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \
      90             :     static base::Histogram* counter(NULL); \
      91             :     if (!counter) \
      92             :       counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
      93             :                                                 base::Histogram::kNoFlags); \
      94             :     DCHECK_EQ(name, counter->histogram_name()); \
      95             :     counter->AddTime(sample); \
      96             :   } while (0)
      97             : 
      98             : // DO NOT USE THIS.  It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES.
      99             : #define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \
     100             :     static base::Histogram* counter(NULL); \
     101             :     if (!counter) \
     102             :       counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
     103             :                                                 base::Histogram::kNoFlags); \
     104             :     DCHECK_EQ(name, counter->histogram_name()); \
     105             :     if ((sample) < (max)) counter->AddTime(sample); \
     106             :   } while (0)
     107             : 
     108             : // Support histograming of an enumerated value.  The samples should always be
     109             : // less than boundary_value.
     110             : 
     111             : #define HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \
     112             :     static base::Histogram* counter(NULL); \
     113             :     if (!counter) \
     114             :       counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \
     115             :           boundary_value + 1, base::Histogram::kNoFlags); \
     116             :     DCHECK_EQ(name, counter->histogram_name()); \
     117             :     counter->Add(sample); \
     118             :   } while (0)
     119             : 
     120             : #define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \
     121             :     static base::Histogram* counter(NULL); \
     122             :     if (!counter) \
     123             :       counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \
     124             :                                                   base::Histogram::kNoFlags); \
     125             :     DCHECK_EQ(name, counter->histogram_name()); \
     126             :     counter->Add(sample); \
     127             :   } while (0)
     128             : 
     129             : 
     130             : //------------------------------------------------------------------------------
     131             : // Define Debug vs non-debug flavors of macros.
     132             : #ifndef NDEBUG
     133             : 
     134             : #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample)
     135             : #define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample)
     136             : #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) HISTOGRAM_PERCENTAGE(\
     137             :     name, under_one_hundred)
     138             : #define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
     139             :     HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count)
     140             : #define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \
     141             :     HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count)
     142             : #define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
     143             :     HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count)
     144             : #define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) \
     145             :     HISTOGRAM_ENUMERATION(name, sample, boundary_value)
     146             : #define DHISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
     147             :     HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges)
     148             : 
     149             : #else  // NDEBUG
     150             : 
     151             : #define DHISTOGRAM_TIMES(name, sample) do {} while (0)
     152             : #define DHISTOGRAM_COUNTS(name, sample) do {} while (0)
     153             : #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) do {} while (0)
     154             : #define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
     155             :     do {} while (0)
     156             : #define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \
     157             :     do {} while (0)
     158             : #define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
     159             :     do {} while (0)
     160             : #define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) do {} while (0)
     161             : #define DHISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
     162             :     do {} while (0)
     163             : 
     164             : #endif  // NDEBUG
     165             : 
     166             : //------------------------------------------------------------------------------
     167             : // The following macros provide typical usage scenarios for callers that wish
     168             : // to record histogram data, and have the data submitted/uploaded via UMA.
     169             : // Not all systems support such UMA, but if they do, the following macros
     170             : // should work with the service.
     171             : 
     172             : #define UMA_HISTOGRAM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
     173             :     name, sample, base::TimeDelta::FromMilliseconds(1), \
     174             :     base::TimeDelta::FromSeconds(10), 50)
     175             : 
     176             : #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
     177             :     name, sample, base::TimeDelta::FromMilliseconds(10), \
     178             :     base::TimeDelta::FromMinutes(3), 50)
     179             : 
     180             : // Use this macro when times can routinely be much longer than 10 seconds.
     181             : #define UMA_HISTOGRAM_LONG_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
     182             :     name, sample, base::TimeDelta::FromMilliseconds(1), \
     183             :     base::TimeDelta::FromHours(1), 50)
     184             : 
     185             : #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \
     186             :     static base::Histogram* counter(NULL); \
     187             :     if (!counter) \
     188             :       counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
     189             :             base::Histogram::kUmaTargetedHistogramFlag); \
     190             :     DCHECK_EQ(name, counter->histogram_name()); \
     191             :     counter->AddTime(sample); \
     192             :   } while (0)
     193             : 
     194             : // DO NOT USE THIS.  It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES.
     195             : #define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \
     196             :     static base::Histogram* counter(NULL); \
     197             :     if (!counter) \
     198             :       counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
     199             :            base::Histogram::kUmaTargetedHistogramFlag); \
     200             :     DCHECK_EQ(name, counter->histogram_name()); \
     201             :     if ((sample) < (max)) counter->AddTime(sample); \
     202             :   } while (0)
     203             : 
     204             : #define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
     205             :     name, sample, 1, 1000000, 50)
     206             : 
     207             : #define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
     208             :     name, sample, 1, 100, 50)
     209             : 
     210             : #define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
     211             :     name, sample, 1, 10000, 50)
     212             : 
     213             : #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \
     214             :     static base::Histogram* counter(NULL); \
     215             :     if (!counter) \
     216             :       counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \
     217             :           base::Histogram::kUmaTargetedHistogramFlag); \
     218             :     DCHECK_EQ(name, counter->histogram_name()); \
     219             :     counter->Add(sample); \
     220             :   } while (0)
     221             : 
     222             : #define UMA_HISTOGRAM_MEMORY_KB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
     223             :     name, sample, 1000, 500000, 50)
     224             : 
     225             : #define UMA_HISTOGRAM_MEMORY_MB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
     226             :     name, sample, 1, 1000, 50)
     227             : 
     228             : #define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
     229             :     UMA_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
     230             : 
     231             : #define UMA_HISTOGRAM_BOOLEAN(name, sample) do { \
     232             :     static base::Histogram* counter(NULL); \
     233             :     if (!counter) \
     234             :       counter = base::BooleanHistogram::FactoryGet(name, \
     235             :           base::Histogram::kUmaTargetedHistogramFlag); \
     236             :     DCHECK_EQ(name, counter->histogram_name()); \
     237             :     counter->AddBoolean(sample); \
     238             :   } while (0)
     239             : 
     240             : #define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \
     241             :     static base::Histogram* counter(NULL); \
     242             :     if (!counter) \
     243             :       counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \
     244             :           boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag); \
     245             :     DCHECK_EQ(name, counter->histogram_name()); \
     246             :     counter->Add(sample); \
     247             :   } while (0)
     248             : 
     249             : #define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \
     250             :     static base::Histogram* counter(NULL); \
     251             :     if (!counter) \
     252             :       counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \
     253             :           base::Histogram::kUmaTargetedHistogramFlag); \
     254             :     DCHECK_EQ(name, counter->histogram_name()); \
     255             :     counter->Add(sample); \
     256             :   } while (0)
     257             : 
     258             : //------------------------------------------------------------------------------
     259             : 
     260             : class BooleanHistogram;
     261             : class CustomHistogram;
     262             : class Histogram;
     263             : class LinearHistogram;
     264             : 
     265             : class Histogram {
     266             :  public:
     267             :   typedef int Sample;  // Used for samples (and ranges of samples).
     268             :   typedef int Count;  // Used to count samples in a bucket.
     269             :   static const Sample kSampleType_MAX = INT_MAX;
     270             :   // Initialize maximum number of buckets in histograms as 16,384.
     271             :   static const size_t kBucketCount_MAX;
     272             : 
     273             :   typedef std::vector<Count> Counts;
     274             :   typedef std::vector<Sample> Ranges;
     275             : 
     276             :   // These enums are used to facilitate deserialization of renderer histograms
     277             :   // into the browser.
     278             :   enum ClassType {
     279             :     HISTOGRAM,
     280             :     LINEAR_HISTOGRAM,
     281             :     BOOLEAN_HISTOGRAM,
     282             :     FLAG_HISTOGRAM,
     283             :     COUNT_HISTOGRAM,
     284             :     CUSTOM_HISTOGRAM,
     285             :     NOT_VALID_IN_RENDERER
     286             :   };
     287             : 
     288             :   enum BucketLayout {
     289             :     EXPONENTIAL,
     290             :     LINEAR,
     291             :     CUSTOM
     292             :   };
     293             : 
     294             :   enum Flags {
     295             :     kNoFlags = 0,
     296             :     kUmaTargetedHistogramFlag = 0x1,  // Histogram should be UMA uploaded.
     297             : 
     298             :     kHexRangePrintingFlag = 0x8000  // Fancy bucket-naming supported.
     299             :   };
     300             : 
     301             :   enum Inconsistencies {
     302             :     NO_INCONSISTENCIES = 0x0,
     303             :     RANGE_CHECKSUM_ERROR = 0x1,
     304             :     BUCKET_ORDER_ERROR = 0x2,
     305             :     COUNT_HIGH_ERROR = 0x4,
     306             :     COUNT_LOW_ERROR = 0x8,
     307             : 
     308             :     NEVER_EXCEEDED_VALUE = 0x10
     309             :   };
     310             : 
     311             :   struct DescriptionPair {
     312             :     Sample sample;
     313             :     const char* description;  // Null means end of a list of pairs.
     314             :   };
     315             : 
     316             :   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
     317             : 
     318             :   //----------------------------------------------------------------------------
     319             :   // Statistic values, developed over the life of the histogram.
     320             : 
     321          15 :   class SampleSet {
     322             :    public:
     323             :     explicit SampleSet();
     324             :     ~SampleSet();
     325             : 
     326             :     // None of the methods in this class are thread-safe.  Callers
     327             :     // must deal with locking themselves.
     328             : 
     329             :     // Adjust size of counts_ for use with given histogram.
     330             :     void Resize(const Histogram& histogram);
     331             : 
     332             :     // Accessor for histogram to make routine additions.
     333             :     void Accumulate(Sample value, Count count, size_t index);
     334             : 
     335             :     // Arithmetic manipulation of corresponding elements of the set.
     336             :     void Add(const SampleSet& other);
     337             : 
     338             :     size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf);
     339             : 
     340           0 :     Count counts(size_t i) const {
     341           0 :        return counts_[i];
     342             :     }
     343             :     Count TotalCount() const;
     344           0 :     int64_t sum() const {
     345           0 :        return sum_;
     346             :     }
     347           0 :     int64_t redundant_count() const {
     348           0 :        return redundant_count_;
     349             :     }
     350           0 :     size_t size() const {
     351           0 :        return counts_.size();
     352             :     }
     353             : 
     354             :    protected:
     355             :     // Actual histogram data is stored in buckets, showing the count of values
     356             :     // that fit into each bucket.
     357             :     Counts counts_;
     358             : 
     359             :     // Save simple stats locally.  Note that this MIGHT get done in base class
     360             :     // without shared memory at some point.
     361             :     int64_t sum_;         // sum of samples.
     362             : 
     363             :     // To help identify memory corruption, we reduntantly save the number of
     364             :     // samples we've accumulated into all of our buckets.  We can compare this
     365             :     // count to the sum of the counts in all buckets, and detect problems.  Note
     366             :     // that due to races in histogram accumulation (if a histogram is indeed
     367             :     // updated on several threads simultaneously), the tallies might mismatch,
     368             :     // and also the snapshotting code may asynchronously get a mismatch (though
     369             :     // generally either race based mismatch cause is VERY rare).
     370             :     int64_t redundant_count_;
     371             :   };
     372             : 
     373             :   //----------------------------------------------------------------------------
     374             :   // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit
     375             :   // default underflow bucket.
     376             :   static Histogram* FactoryGet(const std::string& name,
     377             :                                Sample minimum,
     378             :                                Sample maximum,
     379             :                                size_t bucket_count,
     380             :                                Flags flags);
     381             :   static Histogram* FactoryTimeGet(const std::string& name,
     382             :                                    base::TimeDelta minimum,
     383             :                                    base::TimeDelta maximum,
     384             :                                    size_t bucket_count,
     385             :                                    Flags flags);
     386             : 
     387             :   void Add(int value);
     388             :   void Subtract(int value);
     389             : 
     390             :   // TODO: Currently recording_enabled_ is not used by any Histogram class, but
     391             :   //       rather examined only by the telemetry code (via IsRecordingEnabled).
     392             :   //       Move handling to Histogram's Add() etc after simplifying Histogram.
     393        4815 :   void SetRecordingEnabled(bool aEnabled) { recording_enabled_ = aEnabled; };
     394         911 :   bool IsRecordingEnabled() const { return recording_enabled_; };
     395             : 
     396             :   // This method is an interface, used only by BooleanHistogram.
     397             :   virtual void AddBoolean(bool value);
     398             : 
     399             :   // Accept a TimeDelta to increment.
     400             :   void AddTime(TimeDelta time) {
     401             :     Add(static_cast<int>(time.InMilliseconds()));
     402             :   }
     403             : 
     404             :   virtual void AddSampleSet(const SampleSet& sample);
     405             : 
     406             :   virtual void Clear();
     407             : 
     408             :   // This method is an interface, used only by LinearHistogram.
     409             :   virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
     410             : 
     411             :   // The following methods provide graphical histogram displays.
     412             :   void WriteHTMLGraph(std::string* output) const;
     413             :   void WriteAscii(bool graph_it, const std::string& newline,
     414             :                   std::string* output) const;
     415             : 
     416             :   // Support generic flagging of Histograms.
     417             :   // 0x1 Currently used to mark this histogram to be recorded by UMA..
     418             :   // 0x8000 means print ranges in hex.
     419        4327 :   void SetFlags(Flags flags) { flags_ = static_cast<Flags> (flags_ | flags); }
     420           4 :   void ClearFlags(Flags flags) { flags_ = static_cast<Flags>(flags_ & ~flags); }
     421             :   int flags() const { return flags_; }
     422             : 
     423             :   // Check to see if bucket ranges, counts and tallies in the snapshot are
     424             :   // consistent with the bucket ranges and checksums in our histogram.  This can
     425             :   // produce a false-alarm if a race occurred in the reading of the data during
     426             :   // a SnapShot process, but should otherwise be false at all times (unless we
     427             :   // have memory over-writes, or DRAM failures).
     428             :   virtual Inconsistencies FindCorruption(const SampleSet& snapshot) const;
     429             : 
     430             :   //----------------------------------------------------------------------------
     431             :   // Accessors for factory constuction, serialization and testing.
     432             :   //----------------------------------------------------------------------------
     433             :   virtual ClassType histogram_type() const;
     434        4511 :   const std::string& histogram_name() const { return histogram_name_; }
     435        6807 :   Sample declared_min() const { return declared_min_; }
     436        4342 :   Sample declared_max() const { return declared_max_; }
     437             :   virtual Sample ranges(size_t i) const;
     438             :   uint32_t range_checksum() const { return range_checksum_; }
     439             :   virtual size_t bucket_count() const;
     440             : 
     441             :   // Do a safe atomic snapshot of sample data.  The caller is assumed to
     442             :   // have exclusive access to the destination, |*sample|, and no locking
     443             :   // of it is done here.
     444             :   virtual void SnapshotSample(SampleSet* sample) const;
     445             : 
     446             :   virtual bool HasConstructorArguments(Sample minimum, Sample maximum,
     447             :                                        size_t bucket_count);
     448             : 
     449             :   virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum,
     450             :                                                 TimeDelta maximum,
     451             :                                                 size_t bucket_count);
     452             :   // Return true iff the range_checksum_ matches current ranges_ vector.
     453             :   bool HasValidRangeChecksum() const;
     454             : 
     455             :  protected:
     456             :   Histogram(const std::string& name, Sample minimum,
     457             :             Sample maximum, size_t bucket_count);
     458             :   Histogram(const std::string& name, TimeDelta minimum,
     459             :             TimeDelta maximum, size_t bucket_count);
     460             : 
     461             :   virtual ~Histogram();
     462             : 
     463             :   // Initialize ranges_ mapping.
     464             :   void InitializeBucketRange();
     465             : 
     466             :   // Method to override to skip the display of the i'th bucket if it's empty.
     467             :   virtual bool PrintEmptyBucket(size_t index) const;
     468             : 
     469             :   //----------------------------------------------------------------------------
     470             :   // Methods to override to create histogram with different bucket widths.
     471             :   //----------------------------------------------------------------------------
     472             :   // Find bucket to increment for sample value.
     473             :   virtual size_t BucketIndex(Sample value) const;
     474             :   // Get normalized size, relative to the ranges_[i].
     475             :   virtual double GetBucketSize(Count current, size_t i) const;
     476             : 
     477             :   // Recalculate range_checksum_.
     478             :   void ResetRangeChecksum();
     479             : 
     480             :   // Return a string description of what goes in a given bucket.
     481             :   // Most commonly this is the numeric value, but in derived classes it may
     482             :   // be a name (or string description) given to the bucket.
     483             :   virtual const std::string GetAsciiBucketRange(size_t it) const;
     484             : 
     485             :   //----------------------------------------------------------------------------
     486             :   // Methods to override to create thread safe histogram.
     487             :   //----------------------------------------------------------------------------
     488             :   // Update all our internal data, including histogram
     489             :   virtual void Accumulate(Sample value, Count count, size_t index);
     490             : 
     491             :   //----------------------------------------------------------------------------
     492             :   // Accessors for derived classes.
     493             :   //----------------------------------------------------------------------------
     494             :   void SetBucketRange(size_t i, Sample value);
     495             : 
     496             :   // Validate that ranges_ was created sensibly (top and bottom range
     497             :   // values relate properly to the declared_min_ and declared_max_)..
     498             :   bool ValidateBucketRanges() const;
     499             : 
     500             :   virtual uint32_t CalculateRangeChecksum() const;
     501             : 
     502             :   // Finally, provide the state that changes with the addition of each new
     503             :   // sample.
     504             :   SampleSet sample_;
     505             : 
     506             :  private:
     507             :   friend class StatisticsRecorder;  // To allow it to delete duplicates.
     508             : 
     509             :   // Post constructor initialization.
     510             :   void Initialize();
     511             : 
     512             :   // Checksum function for accumulating range values into a checksum.
     513             :   static uint32_t Crc32(uint32_t sum, Sample range);
     514             : 
     515             :   //----------------------------------------------------------------------------
     516             :   // Helpers for emitting Ascii graphic.  Each method appends data to output.
     517             : 
     518             :   // Find out how large the (graphically) the largest bucket will appear to be.
     519             :   double GetPeakBucketSize(const SampleSet& snapshot) const;
     520             : 
     521             :   // Write a common header message describing this histogram.
     522             :   void WriteAsciiHeader(const SampleSet& snapshot,
     523             :                         Count sample_count, std::string* output) const;
     524             : 
     525             :   // Write information about previous, current, and next buckets.
     526             :   // Information such as cumulative percentage, etc.
     527             :   void WriteAsciiBucketContext(const int64_t past, const Count current,
     528             :                                const int64_t remaining, const size_t i,
     529             :                                std::string* output) const;
     530             : 
     531             :   // Write textual description of the bucket contents (relative to histogram).
     532             :   // Output is the count in the buckets, as well as the percentage.
     533             :   void WriteAsciiBucketValue(Count current, double scaled_sum,
     534             :                              std::string* output) const;
     535             : 
     536             :   // Produce actual graph (set of blank vs non blank char's) for a bucket.
     537             :   void WriteAsciiBucketGraph(double current_size, double max_size,
     538             :                              std::string* output) const;
     539             : 
     540             :   //----------------------------------------------------------------------------
     541             :   // Table for generating Crc32 values.
     542             :   static const uint32_t kCrcTable[256];
     543             :   //----------------------------------------------------------------------------
     544             :   // Invariant values set at/near construction time
     545             : 
     546             :   // ASCII version of original name given to the constructor.  All identically
     547             :   // named instances will be coalesced cross-project.
     548             :   const std::string histogram_name_;
     549             :   Sample declared_min_;  // Less than this goes into counts_[0]
     550             :   Sample declared_max_;  // Over this goes into counts_[bucket_count_ - 1].
     551             :   size_t bucket_count_;  // Dimension of counts_[].
     552             : 
     553             :   // Flag the histogram for recording by UMA via metric_services.h.
     554             :   Flags flags_;
     555             : 
     556             :   // For each index, show the least value that can be stored in the
     557             :   // corresponding bucket. We also append one extra element in this array,
     558             :   // containing kSampleType_MAX, to make calculations easy.
     559             :   // The dimension of ranges_ is bucket_count + 1.
     560             :   Ranges ranges_;
     561             : 
     562             :   // For redundancy, we store a checksum of all the sample ranges when ranges
     563             :   // are generated.  If ever there is ever a difference, then the histogram must
     564             :   // have been corrupted.
     565             :   uint32_t range_checksum_;
     566             : 
     567             :   // When false, new samples are completely ignored.
     568             :   mozilla::Atomic<bool, mozilla::Relaxed> recording_enabled_;
     569             : 
     570             :   DISALLOW_COPY_AND_ASSIGN(Histogram);
     571             : };
     572             : 
     573             : //------------------------------------------------------------------------------
     574             : 
     575             : // LinearHistogram is a more traditional histogram, with evenly spaced
     576             : // buckets.
     577             : class LinearHistogram : public Histogram {
     578             :  public:
     579             :   virtual ~LinearHistogram();
     580             : 
     581             :   /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit
     582             :      default underflow bucket. */
     583             :   static Histogram* FactoryGet(const std::string& name,
     584             :                                Sample minimum,
     585             :                                Sample maximum,
     586             :                                size_t bucket_count,
     587             :                                Flags flags);
     588             :   static Histogram* FactoryTimeGet(const std::string& name,
     589             :                                    TimeDelta minimum,
     590             :                                    TimeDelta maximum,
     591             :                                    size_t bucket_count,
     592             :                                    Flags flags);
     593             : 
     594             :   // Overridden from Histogram:
     595             :   virtual ClassType histogram_type() const;
     596             : 
     597             :   virtual void Accumulate(Sample value, Count count, size_t index);
     598             : 
     599             :   // Store a list of number/text values for use in rendering the histogram.
     600             :   // The last element in the array has a null in its "description" slot.
     601             :   virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
     602             : 
     603             :  protected:
     604             :   LinearHistogram(const std::string& name, Sample minimum,
     605             :                   Sample maximum, size_t bucket_count);
     606             : 
     607             :   LinearHistogram(const std::string& name, TimeDelta minimum,
     608             :                   TimeDelta maximum, size_t bucket_count);
     609             : 
     610             :   // Initialize ranges_ mapping.
     611             :   void InitializeBucketRange();
     612             :   virtual double GetBucketSize(Count current, size_t i) const;
     613             : 
     614             :   // If we have a description for a bucket, then return that.  Otherwise
     615             :   // let parent class provide a (numeric) description.
     616             :   virtual const std::string GetAsciiBucketRange(size_t i) const;
     617             : 
     618             :   // Skip printing of name for numeric range if we have a name (and if this is
     619             :   // an empty bucket).
     620             :   virtual bool PrintEmptyBucket(size_t index) const;
     621             : 
     622             :  private:
     623             :   // For some ranges, we store a printable description of a bucket range.
     624             :   // If there is no desciption, then GetAsciiBucketRange() uses parent class
     625             :   // to provide a description.
     626             :   typedef std::map<Sample, std::string> BucketDescriptionMap;
     627             :   BucketDescriptionMap bucket_description_;
     628             : 
     629             :   DISALLOW_COPY_AND_ASSIGN(LinearHistogram);
     630             : };
     631             : 
     632             : //------------------------------------------------------------------------------
     633             : 
     634             : // BooleanHistogram is a histogram for booleans.
     635           0 : class BooleanHistogram : public LinearHistogram {
     636             :  public:
     637             :   static Histogram* FactoryGet(const std::string& name, Flags flags);
     638             : 
     639             :   virtual ClassType histogram_type() const;
     640             : 
     641             :   virtual void AddBoolean(bool value);
     642             : 
     643             :   virtual void Accumulate(Sample value, Count count, size_t index);
     644             : 
     645             :  protected:
     646             :   explicit BooleanHistogram(const std::string& name);
     647             : 
     648             :   DISALLOW_COPY_AND_ASSIGN(BooleanHistogram);
     649             : };
     650             : 
     651             : //------------------------------------------------------------------------------
     652             : 
     653             : // FlagHistogram is like boolean histogram, but only allows a single off/on value.
     654           0 : class FlagHistogram : public BooleanHistogram
     655             : {
     656             : public:
     657             :   static Histogram *FactoryGet(const std::string &name, Flags flags);
     658             : 
     659             :   virtual ClassType histogram_type() const;
     660             : 
     661             :   virtual void Accumulate(Sample value, Count count, size_t index);
     662             : 
     663             :   virtual void AddSampleSet(const SampleSet& sample);
     664             : 
     665             :   virtual void Clear();
     666             : 
     667             : private:
     668             :   explicit FlagHistogram(const std::string &name);
     669             :   bool mSwitched;
     670             : 
     671             :   DISALLOW_COPY_AND_ASSIGN(FlagHistogram);
     672             : };
     673             : 
     674             : // CountHistogram only allows a single monotic counter value.
     675           0 : class CountHistogram : public LinearHistogram
     676             : {
     677             : public:
     678             :   static Histogram *FactoryGet(const std::string &name, Flags flags);
     679             : 
     680             :   virtual ClassType histogram_type() const;
     681             : 
     682             :   virtual void Accumulate(Sample value, Count count, size_t index);
     683             : 
     684             :   virtual void AddSampleSet(const SampleSet& sample);
     685             : 
     686             : private:
     687             :   explicit CountHistogram(const std::string &name);
     688             : 
     689             :   DISALLOW_COPY_AND_ASSIGN(CountHistogram);
     690             : };
     691             : 
     692             : //------------------------------------------------------------------------------
     693             : 
     694             : // CustomHistogram is a histogram for a set of custom integers.
     695           0 : class CustomHistogram : public Histogram {
     696             :  public:
     697             : 
     698             :   static Histogram* FactoryGet(const std::string& name,
     699             :                                const std::vector<Sample>& custom_ranges,
     700             :                                Flags flags);
     701             : 
     702             :   // Overridden from Histogram:
     703             :   virtual ClassType histogram_type() const;
     704             : 
     705             :  protected:
     706             :   CustomHistogram(const std::string& name,
     707             :                   const std::vector<Sample>& custom_ranges);
     708             : 
     709             :   // Initialize ranges_ mapping.
     710             :   void InitializedCustomBucketRange(const std::vector<Sample>& custom_ranges);
     711             :   virtual double GetBucketSize(Count current, size_t i) const;
     712             : 
     713             :   DISALLOW_COPY_AND_ASSIGN(CustomHistogram);
     714             : };
     715             : 
     716             : //------------------------------------------------------------------------------
     717             : // StatisticsRecorder handles all histograms in the system.  It provides a
     718             : // general place for histograms to register, and supports a global API for
     719             : // accessing (i.e., dumping, or graphing) the data in all the histograms.
     720             : 
     721             : class StatisticsRecorder {
     722             :  public:
     723             :   typedef std::vector<Histogram*> Histograms;
     724             : 
     725             :   StatisticsRecorder();
     726             : 
     727             :   ~StatisticsRecorder();
     728             : 
     729             :   // Find out if histograms can now be registered into our list.
     730             :   static bool IsActive();
     731             : 
     732             :   // Register, or add a new histogram to the collection of statistics. If an
     733             :   // identically named histogram is already registered, then the argument
     734             :   // |histogram| will deleted.  The returned value is always the registered
     735             :   // histogram (either the argument, or the pre-existing registered histogram).
     736             :   static Histogram* RegisterOrDeleteDuplicate(Histogram* histogram);
     737             : 
     738             :   // Methods for printing histograms.  Only histograms which have query as
     739             :   // a substring are written to output (an empty string will process all
     740             :   // registered histograms).
     741             :   static void WriteHTMLGraph(const std::string& query, std::string* output);
     742             :   static void WriteGraph(const std::string& query, std::string* output);
     743             : 
     744             :   // Method for extracting histograms which were marked for use by UMA.
     745             :   static void GetHistograms(Histograms* output);
     746             : 
     747             :   // Find a histogram by name. It matches the exact name. This method is thread
     748             :   // safe.  If a matching histogram is not found, then the |histogram| is
     749             :   // not changed.
     750             :   static bool FindHistogram(const std::string& query, Histogram** histogram);
     751             : 
     752           0 :   static bool dump_on_exit() { return dump_on_exit_; }
     753             : 
     754             :   static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; }
     755             : 
     756             :   // GetSnapshot copies some of the pointers to registered histograms into the
     757             :   // caller supplied vector (Histograms).  Only histograms with names matching
     758             :   // query are returned. The query must be a substring of histogram name for its
     759             :   // pointer to be copied.
     760             :   static void GetSnapshot(const std::string& query, Histograms* snapshot);
     761             : 
     762             : 
     763             :  private:
     764             :   // We keep all registered histograms in a map, from name to histogram.
     765             :   typedef std::map<std::string, Histogram*> HistogramMap;
     766             : 
     767             :   static HistogramMap* histograms_;
     768             : 
     769             :   // lock protects access to the above map.
     770             :   static Lock* lock_;
     771             : 
     772             :   // Dump all known histograms to log.
     773             :   static bool dump_on_exit_;
     774             : 
     775             :   DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder);
     776             : };
     777             : 
     778             : }  // namespace base
     779             : 
     780             : #endif  // BASE_METRICS_HISTOGRAM_H_

Generated by: LCOV version 1.13