// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_METRICS_HISTOGRAM_SAMPLES_H_ #define BASE_METRICS_HISTOGRAM_SAMPLES_H_ #include #include #include #include "base/atomicops.h" #include "base/macros.h" #include "base/metrics/histogram_base.h" namespace base { class Pickle; class PickleIterator; class SampleCountIterator; // HistogramSamples is a container storing all samples of a histogram. All // elements must be of a fixed width to ensure 32/64-bit interoperability. // If this structure changes, bump the version number for kTypeIdHistogram // in persistent_histogram_allocator.cc. class BASE_EXPORT HistogramSamples { public: struct Metadata { // Expected size for 32/64-bit check. static constexpr size_t kExpectedInstanceSize = 24; // Initialized when the sample-set is first created with a value provided // by the caller. It is generally used to identify the sample-set across // threads and processes, though not necessarily uniquely as it is possible // to have multiple sample-sets representing subsets of the data. uint64_t id; // The sum of all the entries, effectivly the sum(sample * count) for // all samples. Despite being atomic, no guarantees are made on the // accuracy of this value; there may be races during histogram // accumulation and snapshotting that we choose to accept. It should // be treated as approximate. #ifdef ARCH_CPU_64_BITS subtle::Atomic64 sum; #else // 32-bit systems don't have atomic 64-bit operations. Use a basic type // and don't worry about "shearing". int64_t sum; #endif // A "redundant" count helps identify memory corruption. It redundantly // stores the total number of samples accumulated in the histogram. We // can compare this count to the sum of the counts (TotalCount() function), // and detect problems. Note, depending on the implementation of different // histogram types, there might be races during histogram accumulation // and snapshotting that we choose to accept. In this case, the tallies // might mismatch even when no memory corruption has happened. HistogramBase::AtomicCount redundant_count; // 4 bytes of padding to explicitly extend this structure to a multiple of // 64-bits. This is required to ensure the structure is the same size on // both 32-bit and 64-bit builds. char padding[4]; }; // Because sturctures held in persistent memory must be POD, there can be no // default constructor to clear the fields. This derived class exists just // to clear them when being allocated on the heap. struct LocalMetadata : Metadata { LocalMetadata() { id = 0; sum = 0; redundant_count = 0; } }; explicit HistogramSamples(uint64_t id); HistogramSamples(uint64_t id, Metadata* meta); virtual ~HistogramSamples(); virtual void Accumulate(HistogramBase::Sample value, HistogramBase::Count count) = 0; virtual HistogramBase::Count GetCount(HistogramBase::Sample value) const = 0; virtual HistogramBase::Count TotalCount() const = 0; virtual void Add(const HistogramSamples& other); // Add from serialized samples. virtual bool AddFromPickle(PickleIterator* iter); virtual void Subtract(const HistogramSamples& other); virtual std::unique_ptr Iterator() const = 0; virtual bool Serialize(Pickle* pickle) const; // Accessor fuctions. uint64_t id() const { return meta_->id; } int64_t sum() const { #ifdef ARCH_CPU_64_BITS return subtle::NoBarrier_Load(&meta_->sum); #else return meta_->sum; #endif } HistogramBase::Count redundant_count() const { return subtle::NoBarrier_Load(&meta_->redundant_count); } protected: // Based on |op| type, add or subtract sample counts data from the iterator. enum Operator { ADD, SUBTRACT }; virtual bool AddSubtractImpl(SampleCountIterator* iter, Operator op) = 0; void IncreaseSum(int64_t diff); void IncreaseRedundantCount(HistogramBase::Count diff); private: // In order to support histograms shared through an external memory segment, // meta values may be the local storage or external storage depending on the // wishes of the derived class. LocalMetadata local_meta_; Metadata* meta_; DISALLOW_COPY_AND_ASSIGN(HistogramSamples); }; class BASE_EXPORT SampleCountIterator { public: virtual ~SampleCountIterator(); virtual bool Done() const = 0; virtual void Next() = 0; // Get the sample and count at current position. // |min| |max| and |count| can be NULL if the value is not of interest. // Requires: !Done(); virtual void Get(HistogramBase::Sample* min, HistogramBase::Sample* max, HistogramBase::Count* count) const = 0; // Get the index of current histogram bucket. // For histograms that don't use predefined buckets, it returns false. // Requires: !Done(); virtual bool GetBucketIndex(size_t* index) const; }; } // namespace base #endif // BASE_METRICS_HISTOGRAM_SAMPLES_H_