1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#ifndef BASE_METRICS_HISTOGRAM_SAMPLES_H_ 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define BASE_METRICS_HISTOGRAM_SAMPLES_H_ 7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 80d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include <stddef.h> 90d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include <stdint.h> 100d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory> 1294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 130d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/atomicops.h" 140d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/macros.h" 150d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/metrics/histogram_base.h" 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass Pickle; 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass PickleIterator; 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass SampleCountIterator; 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 2345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// HistogramSamples is a container storing all samples of a histogram. All 2445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// elements must be of a fixed width to ensure 32/64-bit interoperability. 2545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// If this structure changes, bump the version number for kTypeIdHistogram 2645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// in persistent_histogram_allocator.cc. 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass BASE_EXPORT HistogramSamples { 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 290d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko struct Metadata { 303a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli // Expected size for 32/64-bit check. 313a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli static constexpr size_t kExpectedInstanceSize = 24; 323a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli 330d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // Initialized when the sample-set is first created with a value provided 340d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // by the caller. It is generally used to identify the sample-set across 350d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // threads and processes, though not necessarily uniquely as it is possible 360d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // to have multiple sample-sets representing subsets of the data. 370d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko uint64_t id; 380d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 390d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // The sum of all the entries, effectivly the sum(sample * count) for 400d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // all samples. Despite being atomic, no guarantees are made on the 410d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // accuracy of this value; there may be races during histogram 420d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // accumulation and snapshotting that we choose to accept. It should 430d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // be treated as approximate. 4494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#ifdef ARCH_CPU_64_BITS 4594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez subtle::Atomic64 sum; 4694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#else 4794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // 32-bit systems don't have atomic 64-bit operations. Use a basic type 4894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // and don't worry about "shearing". 490d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int64_t sum; 5094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#endif 510d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 520d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // A "redundant" count helps identify memory corruption. It redundantly 530d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // stores the total number of samples accumulated in the histogram. We 540d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // can compare this count to the sum of the counts (TotalCount() function), 550d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // and detect problems. Note, depending on the implementation of different 560d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // histogram types, there might be races during histogram accumulation 570d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // and snapshotting that we choose to accept. In this case, the tallies 580d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // might mismatch even when no memory corruption has happened. 590d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko HistogramBase::AtomicCount redundant_count; 600d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 613a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli // 4 bytes of padding to explicitly extend this structure to a multiple of 623a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli // 64-bits. This is required to ensure the structure is the same size on 633a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli // both 32-bit and 64-bit builds. 643a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli char padding[4]; 653a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli }; 663a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli 673a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli // Because sturctures held in persistent memory must be POD, there can be no 683a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli // default constructor to clear the fields. This derived class exists just 693a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli // to clear them when being allocated on the heap. 703a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli struct LocalMetadata : Metadata { 713a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli LocalMetadata() { 723a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli id = 0; 733a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli sum = 0; 743a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli redundant_count = 0; 753a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli } 760d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko }; 770d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 780d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko explicit HistogramSamples(uint64_t id); 790d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko HistogramSamples(uint64_t id, Metadata* meta); 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual ~HistogramSamples(); 81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual void Accumulate(HistogramBase::Sample value, 83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat HistogramBase::Count count) = 0; 84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual HistogramBase::Count GetCount(HistogramBase::Sample value) const = 0; 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual HistogramBase::Count TotalCount() const = 0; 86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual void Add(const HistogramSamples& other); 88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Add from serialized samples. 90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual bool AddFromPickle(PickleIterator* iter); 91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual void Subtract(const HistogramSamples& other); 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 9494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez virtual std::unique_ptr<SampleCountIterator> Iterator() const = 0; 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual bool Serialize(Pickle* pickle) const; 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Accessor fuctions. 980d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko uint64_t id() const { return meta_->id; } 9994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez int64_t sum() const { 10094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#ifdef ARCH_CPU_64_BITS 10194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez return subtle::NoBarrier_Load(&meta_->sum); 10294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#else 10394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez return meta_->sum; 10494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#endif 10594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez } 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat HistogramBase::Count redundant_count() const { 1070d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return subtle::NoBarrier_Load(&meta_->redundant_count); 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat protected: 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Based on |op| type, add or subtract sample counts data from the iterator. 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat enum Operator { ADD, SUBTRACT }; 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual bool AddSubtractImpl(SampleCountIterator* iter, Operator op) = 0; 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 1150d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko void IncreaseSum(int64_t diff); 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void IncreaseRedundantCount(HistogramBase::Count diff); 117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 1190d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // In order to support histograms shared through an external memory segment, 1200d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // meta values may be the local storage or external storage depending on the 1210d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // wishes of the derived class. 1223a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli LocalMetadata local_meta_; 1230d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko Metadata* meta_; 1240d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1250d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DISALLOW_COPY_AND_ASSIGN(HistogramSamples); 126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass BASE_EXPORT SampleCountIterator { 129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual ~SampleCountIterator(); 131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual bool Done() const = 0; 133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual void Next() = 0; 134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Get the sample and count at current position. 136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // |min| |max| and |count| can be NULL if the value is not of interest. 137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Requires: !Done(); 138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual void Get(HistogramBase::Sample* min, 139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat HistogramBase::Sample* max, 140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat HistogramBase::Count* count) const = 0; 141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Get the index of current histogram bucket. 143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // For histograms that don't use predefined buckets, it returns false. 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Requires: !Done(); 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual bool GetBucketIndex(size_t* index) const; 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // BASE_METRICS_HISTOGRAM_SAMPLES_H_ 151