LCOV - code coverage report
Current view: directory - ipc/chromium/src/base - histogram.h (source / functions) Found Hit Coverage
Test: app.info Lines: 15 9 60.0 %
Date: 2012-06-02 Functions: 18 9 50.0 %

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

Generated by: LCOV version 1.7