LCOV - app.info - ipc/chromium/src/base/histogram.h

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