Home | History | Annotate | Download | only in metrics
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_METRICS_SPARSE_HISTOGRAM_H_
      6 #define BASE_METRICS_SPARSE_HISTOGRAM_H_
      7 
      8 #include <stddef.h>
      9 #include <stdint.h>
     10 
     11 #include <map>
     12 #include <memory>
     13 #include <string>
     14 
     15 #include "base/base_export.h"
     16 #include "base/compiler_specific.h"
     17 #include "base/logging.h"
     18 #include "base/macros.h"
     19 #include "base/metrics/histogram_base.h"
     20 #include "base/metrics/sample_map.h"
     21 #include "base/synchronization/lock.h"
     22 
     23 namespace base {
     24 
     25 // Sparse histograms are well suited for recording counts of exact sample values
     26 // that are sparsely distributed over a large range.
     27 //
     28 // The implementation uses a lock and a map, whereas other histogram types use a
     29 // vector and no lock. It is thus more costly to add values to, and each value
     30 // stored has more overhead, compared to the other histogram types. However it
     31 // may be more efficient in memory if the total number of sample values is small
     32 // compared to the range of their values.
     33 //
     34 // UMA_HISTOGRAM_ENUMERATION would be better suited for a smaller range of
     35 // enumerations that are (nearly) contiguous. Also for code that is expected to
     36 // run often or in a tight loop.
     37 //
     38 // UMA_HISTOGRAM_SPARSE_SLOWLY is good for sparsely distributed and or
     39 // infrequently recorded values.
     40 //
     41 // For instance, Sqlite.Version.* are SPARSE because for any given database,
     42 // there's going to be exactly one version logged, meaning no gain to having a
     43 // pre-allocated vector of slots once the fleet gets to version 4 or 5 or 10.
     44 // Likewise Sqlite.Error.* are SPARSE, because most databases generate few or no
     45 // errors and there are large gaps in the set of possible errors.
     46 #define UMA_HISTOGRAM_SPARSE_SLOWLY(name, sample) \
     47     do { \
     48       base::HistogramBase* histogram = base::SparseHistogram::FactoryGet( \
     49           name, base::HistogramBase::kUmaTargetedHistogramFlag); \
     50       histogram->Add(sample); \
     51     } while (0)
     52 
     53 class HistogramSamples;
     54 class PersistentHistogramAllocator;
     55 
     56 class BASE_EXPORT SparseHistogram : public HistogramBase {
     57  public:
     58   // If there's one with same name, return the existing one. If not, create a
     59   // new one.
     60   static HistogramBase* FactoryGet(const std::string& name, int32_t flags);
     61 
     62   // Create a histogram using data in persistent storage. The allocator must
     63   // live longer than the created sparse histogram.
     64   static std::unique_ptr<HistogramBase> PersistentCreate(
     65       PersistentHistogramAllocator* allocator,
     66       const std::string& name,
     67       HistogramSamples::Metadata* meta,
     68       HistogramSamples::Metadata* logged_meta);
     69 
     70   ~SparseHistogram() override;
     71 
     72   // HistogramBase implementation:
     73   uint64_t name_hash() const override;
     74   HistogramType GetHistogramType() const override;
     75   bool HasConstructionArguments(Sample expected_minimum,
     76                                 Sample expected_maximum,
     77                                 uint32_t expected_bucket_count) const override;
     78   void Add(Sample value) override;
     79   void AddCount(Sample value, int count) override;
     80   void AddSamples(const HistogramSamples& samples) override;
     81   bool AddSamplesFromPickle(base::PickleIterator* iter) override;
     82   std::unique_ptr<HistogramSamples> SnapshotSamples() const override;
     83   std::unique_ptr<HistogramSamples> SnapshotDelta() override;
     84   std::unique_ptr<HistogramSamples> SnapshotFinalDelta() const override;
     85   void WriteHTMLGraph(std::string* output) const override;
     86   void WriteAscii(std::string* output) const override;
     87 
     88  protected:
     89   // HistogramBase implementation:
     90   bool SerializeInfoImpl(base::Pickle* pickle) const override;
     91 
     92  private:
     93   // Clients should always use FactoryGet to create SparseHistogram.
     94   explicit SparseHistogram(const std::string& name);
     95 
     96   SparseHistogram(PersistentHistogramAllocator* allocator,
     97                   const std::string& name,
     98                   HistogramSamples::Metadata* meta,
     99                   HistogramSamples::Metadata* logged_meta);
    100 
    101   friend BASE_EXPORT HistogramBase* DeserializeHistogramInfo(
    102       base::PickleIterator* iter);
    103   static HistogramBase* DeserializeInfoImpl(base::PickleIterator* iter);
    104 
    105   void GetParameters(DictionaryValue* params) const override;
    106   void GetCountAndBucketData(Count* count,
    107                              int64_t* sum,
    108                              ListValue* buckets) const override;
    109 
    110   // Helpers for emitting Ascii graphic.  Each method appends data to output.
    111   void WriteAsciiImpl(bool graph_it,
    112                       const std::string& newline,
    113                       std::string* output) const;
    114 
    115   // Write a common header message describing this histogram.
    116   void WriteAsciiHeader(const Count total_count,
    117                         std::string* output) const;
    118 
    119   // For constuctor calling.
    120   friend class SparseHistogramTest;
    121 
    122   // Protects access to |samples_|.
    123   mutable base::Lock lock_;
    124 
    125   // Flag to indicate if PrepareFinalDelta has been previously called.
    126   mutable bool final_delta_created_ = false;
    127 
    128   std::unique_ptr<HistogramSamples> samples_;
    129   std::unique_ptr<HistogramSamples> logged_samples_;
    130 
    131   DISALLOW_COPY_AND_ASSIGN(SparseHistogram);
    132 };
    133 
    134 }  // namespace base
    135 
    136 #endif  // BASE_METRICS_SPARSE_HISTOGRAM_H_
    137