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 // Expected size for 32/64-bit check. 31 static constexpr size_t kExpectedInstanceSize = 24; 32 33 // Initialized when the sample-set is first created with a value provided 34 // by the caller. It is generally used to identify the sample-set across 35 // threads and processes, though not necessarily uniquely as it is possible 36 // to have multiple sample-sets representing subsets of the data. 37 uint64_t id; 38 39 // The sum of all the entries, effectivly the sum(sample * count) for 40 // all samples. Despite being atomic, no guarantees are made on the 41 // accuracy of this value; there may be races during histogram 42 // accumulation and snapshotting that we choose to accept. It should 43 // be treated as approximate. 44 #ifdef ARCH_CPU_64_BITS 45 subtle::Atomic64 sum; 46 #else 47 // 32-bit systems don't have atomic 64-bit operations. Use a basic type 48 // and don't worry about "shearing". 49 int64_t sum; 50 #endif 51 52 // A "redundant" count helps identify memory corruption. It redundantly 53 // stores the total number of samples accumulated in the histogram. We 54 // can compare this count to the sum of the counts (TotalCount() function), 55 // and detect problems. Note, depending on the implementation of different 56 // histogram types, there might be races during histogram accumulation 57 // and snapshotting that we choose to accept. In this case, the tallies 58 // might mismatch even when no memory corruption has happened. 59 HistogramBase::AtomicCount redundant_count; 60 61 // 4 bytes of padding to explicitly extend this structure to a multiple of 62 // 64-bits. This is required to ensure the structure is the same size on 63 // both 32-bit and 64-bit builds. 64 char padding[4]; 65 }; 66 67 // Because sturctures held in persistent memory must be POD, there can be no 68 // default constructor to clear the fields. This derived class exists just 69 // to clear them when being allocated on the heap. 70 struct LocalMetadata : Metadata { LocalMetadataLocalMetadata71 LocalMetadata() { 72 id = 0; 73 sum = 0; 74 redundant_count = 0; 75 } 76 }; 77 78 explicit HistogramSamples(uint64_t id); 79 HistogramSamples(uint64_t id, Metadata* meta); 80 virtual ~HistogramSamples(); 81 82 virtual void Accumulate(HistogramBase::Sample value, 83 HistogramBase::Count count) = 0; 84 virtual HistogramBase::Count GetCount(HistogramBase::Sample value) const = 0; 85 virtual HistogramBase::Count TotalCount() const = 0; 86 87 virtual void Add(const HistogramSamples& other); 88 89 // Add from serialized samples. 90 virtual bool AddFromPickle(PickleIterator* iter); 91 92 virtual void Subtract(const HistogramSamples& other); 93 94 virtual std::unique_ptr<SampleCountIterator> Iterator() const = 0; 95 virtual bool Serialize(Pickle* pickle) const; 96 97 // Accessor fuctions. id()98 uint64_t id() const { return meta_->id; } sum()99 int64_t sum() const { 100 #ifdef ARCH_CPU_64_BITS 101 return subtle::NoBarrier_Load(&meta_->sum); 102 #else 103 return meta_->sum; 104 #endif 105 } redundant_count()106 HistogramBase::Count redundant_count() const { 107 return subtle::NoBarrier_Load(&meta_->redundant_count); 108 } 109 110 protected: 111 // Based on |op| type, add or subtract sample counts data from the iterator. 112 enum Operator { ADD, SUBTRACT }; 113 virtual bool AddSubtractImpl(SampleCountIterator* iter, Operator op) = 0; 114 115 void IncreaseSum(int64_t diff); 116 void IncreaseRedundantCount(HistogramBase::Count diff); 117 118 private: 119 // In order to support histograms shared through an external memory segment, 120 // meta values may be the local storage or external storage depending on the 121 // wishes of the derived class. 122 LocalMetadata local_meta_; 123 Metadata* meta_; 124 125 DISALLOW_COPY_AND_ASSIGN(HistogramSamples); 126 }; 127 128 class BASE_EXPORT SampleCountIterator { 129 public: 130 virtual ~SampleCountIterator(); 131 132 virtual bool Done() const = 0; 133 virtual void Next() = 0; 134 135 // Get the sample and count at current position. 136 // |min| |max| and |count| can be NULL if the value is not of interest. 137 // Requires: !Done(); 138 virtual void Get(HistogramBase::Sample* min, 139 HistogramBase::Sample* max, 140 HistogramBase::Count* count) const = 0; 141 142 // Get the index of current histogram bucket. 143 // For histograms that don't use predefined buckets, it returns false. 144 // Requires: !Done(); 145 virtual bool GetBucketIndex(size_t* index) const; 146 }; 147 148 } // namespace base 149 150 #endif // BASE_METRICS_HISTOGRAM_SAMPLES_H_ 151