1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file. 4*635a8641SAndroid Build Coastguard Worker 5*635a8641SAndroid Build Coastguard Worker // SampleVector implements HistogramSamples interface. It is used by all 6*635a8641SAndroid Build Coastguard Worker // Histogram based classes to store samples. 7*635a8641SAndroid Build Coastguard Worker 8*635a8641SAndroid Build Coastguard Worker #ifndef BASE_METRICS_SAMPLE_VECTOR_H_ 9*635a8641SAndroid Build Coastguard Worker #define BASE_METRICS_SAMPLE_VECTOR_H_ 10*635a8641SAndroid Build Coastguard Worker 11*635a8641SAndroid Build Coastguard Worker #include <stddef.h> 12*635a8641SAndroid Build Coastguard Worker #include <stdint.h> 13*635a8641SAndroid Build Coastguard Worker 14*635a8641SAndroid Build Coastguard Worker #include <memory> 15*635a8641SAndroid Build Coastguard Worker #include <vector> 16*635a8641SAndroid Build Coastguard Worker 17*635a8641SAndroid Build Coastguard Worker #include "base/atomicops.h" 18*635a8641SAndroid Build Coastguard Worker #include "base/compiler_specific.h" 19*635a8641SAndroid Build Coastguard Worker #include "base/gtest_prod_util.h" 20*635a8641SAndroid Build Coastguard Worker #include "base/macros.h" 21*635a8641SAndroid Build Coastguard Worker #include "base/metrics/bucket_ranges.h" 22*635a8641SAndroid Build Coastguard Worker #include "base/metrics/histogram_base.h" 23*635a8641SAndroid Build Coastguard Worker #include "base/metrics/histogram_samples.h" 24*635a8641SAndroid Build Coastguard Worker #include "base/metrics/persistent_memory_allocator.h" 25*635a8641SAndroid Build Coastguard Worker 26*635a8641SAndroid Build Coastguard Worker namespace base { 27*635a8641SAndroid Build Coastguard Worker 28*635a8641SAndroid Build Coastguard Worker class BucketRanges; 29*635a8641SAndroid Build Coastguard Worker 30*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT SampleVectorBase : public HistogramSamples { 31*635a8641SAndroid Build Coastguard Worker public: 32*635a8641SAndroid Build Coastguard Worker SampleVectorBase(uint64_t id, 33*635a8641SAndroid Build Coastguard Worker Metadata* meta, 34*635a8641SAndroid Build Coastguard Worker const BucketRanges* bucket_ranges); 35*635a8641SAndroid Build Coastguard Worker ~SampleVectorBase() override; 36*635a8641SAndroid Build Coastguard Worker 37*635a8641SAndroid Build Coastguard Worker // HistogramSamples: 38*635a8641SAndroid Build Coastguard Worker void Accumulate(HistogramBase::Sample value, 39*635a8641SAndroid Build Coastguard Worker HistogramBase::Count count) override; 40*635a8641SAndroid Build Coastguard Worker HistogramBase::Count GetCount(HistogramBase::Sample value) const override; 41*635a8641SAndroid Build Coastguard Worker HistogramBase::Count TotalCount() const override; 42*635a8641SAndroid Build Coastguard Worker std::unique_ptr<SampleCountIterator> Iterator() const override; 43*635a8641SAndroid Build Coastguard Worker 44*635a8641SAndroid Build Coastguard Worker // Get count of a specific bucket. 45*635a8641SAndroid Build Coastguard Worker HistogramBase::Count GetCountAtIndex(size_t bucket_index) const; 46*635a8641SAndroid Build Coastguard Worker 47*635a8641SAndroid Build Coastguard Worker // Access the bucket ranges held externally. bucket_ranges()48*635a8641SAndroid Build Coastguard Worker const BucketRanges* bucket_ranges() const { return bucket_ranges_; } 49*635a8641SAndroid Build Coastguard Worker 50*635a8641SAndroid Build Coastguard Worker protected: 51*635a8641SAndroid Build Coastguard Worker bool AddSubtractImpl( 52*635a8641SAndroid Build Coastguard Worker SampleCountIterator* iter, 53*635a8641SAndroid Build Coastguard Worker HistogramSamples::Operator op) override; // |op| is ADD or SUBTRACT. 54*635a8641SAndroid Build Coastguard Worker 55*635a8641SAndroid Build Coastguard Worker virtual size_t GetBucketIndex(HistogramBase::Sample value) const; 56*635a8641SAndroid Build Coastguard Worker 57*635a8641SAndroid Build Coastguard Worker // Moves the single-sample value to a mounted "counts" array. 58*635a8641SAndroid Build Coastguard Worker void MoveSingleSampleToCounts(); 59*635a8641SAndroid Build Coastguard Worker 60*635a8641SAndroid Build Coastguard Worker // Mounts (creating if necessary) an array of "counts" for multi-value 61*635a8641SAndroid Build Coastguard Worker // storage. 62*635a8641SAndroid Build Coastguard Worker void MountCountsStorageAndMoveSingleSample(); 63*635a8641SAndroid Build Coastguard Worker 64*635a8641SAndroid Build Coastguard Worker // Mounts "counts" storage that already exists. This does not attempt to move 65*635a8641SAndroid Build Coastguard Worker // any single-sample information to that storage as that would violate the 66*635a8641SAndroid Build Coastguard Worker // "const" restriction that is often used to indicate read-only memory. 67*635a8641SAndroid Build Coastguard Worker virtual bool MountExistingCountsStorage() const = 0; 68*635a8641SAndroid Build Coastguard Worker 69*635a8641SAndroid Build Coastguard Worker // Creates "counts" storage and returns a pointer to it. Ownership of the 70*635a8641SAndroid Build Coastguard Worker // array remains with the called method but will never change. This must be 71*635a8641SAndroid Build Coastguard Worker // called while some sort of lock is held to prevent reentry. 72*635a8641SAndroid Build Coastguard Worker virtual HistogramBase::Count* CreateCountsStorageWhileLocked() = 0; 73*635a8641SAndroid Build Coastguard Worker counts()74*635a8641SAndroid Build Coastguard Worker HistogramBase::AtomicCount* counts() { 75*635a8641SAndroid Build Coastguard Worker return reinterpret_cast<HistogramBase::AtomicCount*>( 76*635a8641SAndroid Build Coastguard Worker subtle::Acquire_Load(&counts_)); 77*635a8641SAndroid Build Coastguard Worker } 78*635a8641SAndroid Build Coastguard Worker counts()79*635a8641SAndroid Build Coastguard Worker const HistogramBase::AtomicCount* counts() const { 80*635a8641SAndroid Build Coastguard Worker return reinterpret_cast<HistogramBase::AtomicCount*>( 81*635a8641SAndroid Build Coastguard Worker subtle::Acquire_Load(&counts_)); 82*635a8641SAndroid Build Coastguard Worker } 83*635a8641SAndroid Build Coastguard Worker set_counts(const HistogramBase::AtomicCount * counts)84*635a8641SAndroid Build Coastguard Worker void set_counts(const HistogramBase::AtomicCount* counts) const { 85*635a8641SAndroid Build Coastguard Worker subtle::Release_Store(&counts_, reinterpret_cast<uintptr_t>(counts)); 86*635a8641SAndroid Build Coastguard Worker } 87*635a8641SAndroid Build Coastguard Worker counts_size()88*635a8641SAndroid Build Coastguard Worker size_t counts_size() const { return bucket_ranges_->bucket_count(); } 89*635a8641SAndroid Build Coastguard Worker 90*635a8641SAndroid Build Coastguard Worker private: 91*635a8641SAndroid Build Coastguard Worker friend class SampleVectorTest; 92*635a8641SAndroid Build Coastguard Worker FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts); 93*635a8641SAndroid Build Coastguard Worker FRIEND_TEST_ALL_PREFIXES(SharedHistogramTest, CorruptSampleCounts); 94*635a8641SAndroid Build Coastguard Worker 95*635a8641SAndroid Build Coastguard Worker // |counts_| is actually a pointer to a HistogramBase::AtomicCount array but 96*635a8641SAndroid Build Coastguard Worker // is held as an AtomicWord for concurrency reasons. When combined with the 97*635a8641SAndroid Build Coastguard Worker // single_sample held in the metadata, there are four possible states: 98*635a8641SAndroid Build Coastguard Worker // 1) single_sample == zero, counts_ == null 99*635a8641SAndroid Build Coastguard Worker // 2) single_sample != zero, counts_ == null 100*635a8641SAndroid Build Coastguard Worker // 3) single_sample != zero, counts_ != null BUT IS EMPTY 101*635a8641SAndroid Build Coastguard Worker // 4) single_sample == zero, counts_ != null and may have data 102*635a8641SAndroid Build Coastguard Worker // Once |counts_| is set, it can never revert and any existing single-sample 103*635a8641SAndroid Build Coastguard Worker // must be moved to this storage. It is mutable because changing it doesn't 104*635a8641SAndroid Build Coastguard Worker // change the (const) data but must adapt if a non-const object causes the 105*635a8641SAndroid Build Coastguard Worker // storage to be allocated and updated. 106*635a8641SAndroid Build Coastguard Worker mutable subtle::AtomicWord counts_ = 0; 107*635a8641SAndroid Build Coastguard Worker 108*635a8641SAndroid Build Coastguard Worker // Shares the same BucketRanges with Histogram object. 109*635a8641SAndroid Build Coastguard Worker const BucketRanges* const bucket_ranges_; 110*635a8641SAndroid Build Coastguard Worker 111*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(SampleVectorBase); 112*635a8641SAndroid Build Coastguard Worker }; 113*635a8641SAndroid Build Coastguard Worker 114*635a8641SAndroid Build Coastguard Worker // A sample vector that uses local memory for the counts array. 115*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT SampleVector : public SampleVectorBase { 116*635a8641SAndroid Build Coastguard Worker public: 117*635a8641SAndroid Build Coastguard Worker explicit SampleVector(const BucketRanges* bucket_ranges); 118*635a8641SAndroid Build Coastguard Worker SampleVector(uint64_t id, const BucketRanges* bucket_ranges); 119*635a8641SAndroid Build Coastguard Worker ~SampleVector() override; 120*635a8641SAndroid Build Coastguard Worker 121*635a8641SAndroid Build Coastguard Worker private: 122*635a8641SAndroid Build Coastguard Worker // SampleVectorBase: 123*635a8641SAndroid Build Coastguard Worker bool MountExistingCountsStorage() const override; 124*635a8641SAndroid Build Coastguard Worker HistogramBase::Count* CreateCountsStorageWhileLocked() override; 125*635a8641SAndroid Build Coastguard Worker 126*635a8641SAndroid Build Coastguard Worker // Simple local storage for counts. 127*635a8641SAndroid Build Coastguard Worker mutable std::vector<HistogramBase::AtomicCount> local_counts_; 128*635a8641SAndroid Build Coastguard Worker 129*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(SampleVector); 130*635a8641SAndroid Build Coastguard Worker }; 131*635a8641SAndroid Build Coastguard Worker 132*635a8641SAndroid Build Coastguard Worker // A sample vector that uses persistent memory for the counts array. 133*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT PersistentSampleVector : public SampleVectorBase { 134*635a8641SAndroid Build Coastguard Worker public: 135*635a8641SAndroid Build Coastguard Worker PersistentSampleVector(uint64_t id, 136*635a8641SAndroid Build Coastguard Worker const BucketRanges* bucket_ranges, 137*635a8641SAndroid Build Coastguard Worker Metadata* meta, 138*635a8641SAndroid Build Coastguard Worker const DelayedPersistentAllocation& counts); 139*635a8641SAndroid Build Coastguard Worker ~PersistentSampleVector() override; 140*635a8641SAndroid Build Coastguard Worker 141*635a8641SAndroid Build Coastguard Worker private: 142*635a8641SAndroid Build Coastguard Worker // SampleVectorBase: 143*635a8641SAndroid Build Coastguard Worker bool MountExistingCountsStorage() const override; 144*635a8641SAndroid Build Coastguard Worker HistogramBase::Count* CreateCountsStorageWhileLocked() override; 145*635a8641SAndroid Build Coastguard Worker 146*635a8641SAndroid Build Coastguard Worker // Persistent storage for counts. 147*635a8641SAndroid Build Coastguard Worker DelayedPersistentAllocation persistent_counts_; 148*635a8641SAndroid Build Coastguard Worker 149*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(PersistentSampleVector); 150*635a8641SAndroid Build Coastguard Worker }; 151*635a8641SAndroid Build Coastguard Worker 152*635a8641SAndroid Build Coastguard Worker // An iterator for sample vectors. This could be defined privately in the .cc 153*635a8641SAndroid Build Coastguard Worker // file but is here for easy testing. 154*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT SampleVectorIterator : public SampleCountIterator { 155*635a8641SAndroid Build Coastguard Worker public: 156*635a8641SAndroid Build Coastguard Worker SampleVectorIterator(const std::vector<HistogramBase::AtomicCount>* counts, 157*635a8641SAndroid Build Coastguard Worker const BucketRanges* bucket_ranges); 158*635a8641SAndroid Build Coastguard Worker SampleVectorIterator(const HistogramBase::AtomicCount* counts, 159*635a8641SAndroid Build Coastguard Worker size_t counts_size, 160*635a8641SAndroid Build Coastguard Worker const BucketRanges* bucket_ranges); 161*635a8641SAndroid Build Coastguard Worker ~SampleVectorIterator() override; 162*635a8641SAndroid Build Coastguard Worker 163*635a8641SAndroid Build Coastguard Worker // SampleCountIterator implementation: 164*635a8641SAndroid Build Coastguard Worker bool Done() const override; 165*635a8641SAndroid Build Coastguard Worker void Next() override; 166*635a8641SAndroid Build Coastguard Worker void Get(HistogramBase::Sample* min, 167*635a8641SAndroid Build Coastguard Worker int64_t* max, 168*635a8641SAndroid Build Coastguard Worker HistogramBase::Count* count) const override; 169*635a8641SAndroid Build Coastguard Worker 170*635a8641SAndroid Build Coastguard Worker // SampleVector uses predefined buckets, so iterator can return bucket index. 171*635a8641SAndroid Build Coastguard Worker bool GetBucketIndex(size_t* index) const override; 172*635a8641SAndroid Build Coastguard Worker 173*635a8641SAndroid Build Coastguard Worker private: 174*635a8641SAndroid Build Coastguard Worker void SkipEmptyBuckets(); 175*635a8641SAndroid Build Coastguard Worker 176*635a8641SAndroid Build Coastguard Worker const HistogramBase::AtomicCount* counts_; 177*635a8641SAndroid Build Coastguard Worker size_t counts_size_; 178*635a8641SAndroid Build Coastguard Worker const BucketRanges* bucket_ranges_; 179*635a8641SAndroid Build Coastguard Worker 180*635a8641SAndroid Build Coastguard Worker size_t index_; 181*635a8641SAndroid Build Coastguard Worker }; 182*635a8641SAndroid Build Coastguard Worker 183*635a8641SAndroid Build Coastguard Worker } // namespace base 184*635a8641SAndroid Build Coastguard Worker 185*635a8641SAndroid Build Coastguard Worker #endif // BASE_METRICS_SAMPLE_VECTOR_H_ 186