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_HISTOGRAM_SAMPLES_H_
6 #define BASE_METRICS_HISTOGRAM_SAMPLES_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <memory>
12 
13 #include "base/atomicops.h"
14 #include "base/macros.h"
15 #include "base/metrics/histogram_base.h"
16 
17 namespace base {
18 
19 class Pickle;
20 class PickleIterator;
21 class SampleCountIterator;
22 
23 // HistogramSamples is a container storing all samples of a histogram. All
24 // elements must be of a fixed width to ensure 32/64-bit interoperability.
25 // If this structure changes, bump the version number for kTypeIdHistogram
26 // in persistent_histogram_allocator.cc.
27 class BASE_EXPORT HistogramSamples {
28  public:
29   struct Metadata {
30     // Initialized when the sample-set is first created with a value provided
31     // by the caller. It is generally used to identify the sample-set across
32     // threads and processes, though not necessarily uniquely as it is possible
33     // to have multiple sample-sets representing subsets of the data.
34     uint64_t id;
35 
36     // The sum of all the entries, effectivly the sum(sample * count) for
37     // all samples. Despite being atomic, no guarantees are made on the
38     // accuracy of this value; there may be races during histogram
39     // accumulation and snapshotting that we choose to accept. It should
40     // be treated as approximate.
41 #ifdef ARCH_CPU_64_BITS
42     subtle::Atomic64 sum;
43 #else
44     // 32-bit systems don't have atomic 64-bit operations. Use a basic type
45     // and don't worry about "shearing".
46     int64_t sum;
47 #endif
48 
49     // A "redundant" count helps identify memory corruption. It redundantly
50     // stores the total number of samples accumulated in the histogram. We
51     // can compare this count to the sum of the counts (TotalCount() function),
52     // and detect problems. Note, depending on the implementation of different
53     // histogram types, there might be races during histogram accumulation
54     // and snapshotting that we choose to accept. In this case, the tallies
55     // might mismatch even when no memory corruption has happened.
56     HistogramBase::AtomicCount redundant_count;
57 
MetadataMetadata58     Metadata() : id(0), sum(0), redundant_count(0) {}
59   };
60 
61   explicit HistogramSamples(uint64_t id);
62   HistogramSamples(uint64_t id, Metadata* meta);
63   virtual ~HistogramSamples();
64 
65   virtual void Accumulate(HistogramBase::Sample value,
66                           HistogramBase::Count count) = 0;
67   virtual HistogramBase::Count GetCount(HistogramBase::Sample value) const = 0;
68   virtual HistogramBase::Count TotalCount() const = 0;
69 
70   virtual void Add(const HistogramSamples& other);
71 
72   // Add from serialized samples.
73   virtual bool AddFromPickle(PickleIterator* iter);
74 
75   virtual void Subtract(const HistogramSamples& other);
76 
77   virtual std::unique_ptr<SampleCountIterator> Iterator() const = 0;
78   virtual bool Serialize(Pickle* pickle) const;
79 
80   // Accessor fuctions.
id()81   uint64_t id() const { return meta_->id; }
sum()82   int64_t sum() const {
83 #ifdef ARCH_CPU_64_BITS
84     return subtle::NoBarrier_Load(&meta_->sum);
85 #else
86     return meta_->sum;
87 #endif
88   }
redundant_count()89   HistogramBase::Count redundant_count() const {
90     return subtle::NoBarrier_Load(&meta_->redundant_count);
91   }
92 
93  protected:
94   // Based on |op| type, add or subtract sample counts data from the iterator.
95   enum Operator { ADD, SUBTRACT };
96   virtual bool AddSubtractImpl(SampleCountIterator* iter, Operator op) = 0;
97 
98   void IncreaseSum(int64_t diff);
99   void IncreaseRedundantCount(HistogramBase::Count diff);
100 
101  private:
102   // In order to support histograms shared through an external memory segment,
103   // meta values may be the local storage or external storage depending on the
104   // wishes of the derived class.
105   Metadata local_meta_;
106   Metadata* meta_;
107 
108   DISALLOW_COPY_AND_ASSIGN(HistogramSamples);
109 };
110 
111 class BASE_EXPORT SampleCountIterator {
112  public:
113   virtual ~SampleCountIterator();
114 
115   virtual bool Done() const = 0;
116   virtual void Next() = 0;
117 
118   // Get the sample and count at current position.
119   // |min| |max| and |count| can be NULL if the value is not of interest.
120   // Requires: !Done();
121   virtual void Get(HistogramBase::Sample* min,
122                    HistogramBase::Sample* max,
123                    HistogramBase::Count* count) const = 0;
124 
125   // Get the index of current histogram bucket.
126   // For histograms that don't use predefined buckets, it returns false.
127   // Requires: !Done();
128   virtual bool GetBucketIndex(size_t* index) const;
129 };
130 
131 }  // namespace base
132 
133 #endif  // BASE_METRICS_HISTOGRAM_SAMPLES_H_
134