1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // 5 // BucketRanges stores the vector of ranges that delimit what samples are 6 // tallied in the corresponding buckets of a histogram. Histograms that have 7 // same ranges for all their corresponding buckets should share the same 8 // BucketRanges object. 9 // 10 // E.g. A 5 buckets LinearHistogram with 1 as minimal value and 4 as maximal 11 // value will need a BucketRanges with 6 ranges: 12 // 0, 1, 2, 3, 4, INT_MAX 13 // 14 // TODO(kaiwang): Currently we keep all negative values in 0~1 bucket. Consider 15 // changing 0 to INT_MIN. 16 17 #ifndef BASE_METRICS_BUCKET_RANGES_H_ 18 #define BASE_METRICS_BUCKET_RANGES_H_ 19 20 #include <limits.h> 21 #include <stddef.h> 22 #include <stdint.h> 23 24 #include <atomic> 25 #include <vector> 26 27 #include "base/base_export.h" 28 #include "base/check_op.h" 29 #include "base/metrics/histogram_base.h" 30 31 namespace base { 32 33 class BASE_EXPORT BucketRanges { 34 public: 35 typedef std::vector<HistogramBase::Sample> Ranges; 36 37 explicit BucketRanges(size_t num_ranges); 38 39 BucketRanges(const BucketRanges&) = delete; 40 BucketRanges& operator=(const BucketRanges&) = delete; 41 42 ~BucketRanges(); 43 size()44 size_t size() const { return ranges_.size(); } range(size_t i)45 HistogramBase::Sample range(size_t i) const { return ranges_[i]; } set_range(size_t i,HistogramBase::Sample value)46 void set_range(size_t i, HistogramBase::Sample value) { 47 DCHECK_LT(i, ranges_.size()); 48 DCHECK_GE(value, 0); 49 ranges_[i] = value; 50 } checksum()51 uint32_t checksum() const { return checksum_; } set_checksum(uint32_t checksum)52 void set_checksum(uint32_t checksum) { checksum_ = checksum; } 53 54 // A bucket is defined by a consecutive pair of entries in |ranges|, so there 55 // is one fewer bucket than there are ranges. For example, if |ranges| is 56 // [0, 1, 3, 7, INT_MAX], then the buckets in this histogram are 57 // [0, 1), [1, 3), [3, 7), and [7, INT_MAX). bucket_count()58 size_t bucket_count() const { return ranges_.size() - 1; } 59 60 // Checksum methods to verify whether the ranges are corrupted (e.g. bad 61 // memory access). 62 uint32_t CalculateChecksum() const; 63 bool HasValidChecksum() const; 64 void ResetChecksum(); 65 66 // Return true iff |other| object has same ranges_ as |this| object's ranges_. 67 bool Equals(const BucketRanges* other) const; 68 69 // Set and get a reference into persistent memory where this bucket data 70 // can be found (and re-used). These calls are internally atomic with no 71 // safety against overwriting an existing value since though it is wasteful 72 // to have multiple identical persistent records, it is still safe. set_persistent_reference(uint32_t ref)73 void set_persistent_reference(uint32_t ref) const { 74 persistent_reference_.store(ref, std::memory_order_release); 75 } persistent_reference()76 uint32_t persistent_reference() const { 77 return persistent_reference_.load(std::memory_order_acquire); 78 } 79 80 private: 81 // A monotonically increasing list of values which determine which bucket to 82 // put a sample into. For each index, show the smallest sample that can be 83 // added to the corresponding bucket. 84 Ranges ranges_; 85 86 // Checksum for the conntents of ranges_. Used to detect random over-writes 87 // of our data, and to quickly see if some other BucketRanges instance is 88 // possibly Equal() to this instance. 89 // TODO(kaiwang): Consider change this to uint64_t. Because we see a lot of 90 // noise on UMA dashboard. 91 uint32_t checksum_; 92 93 // A reference into a global PersistentMemoryAllocator where the ranges 94 // information is stored. This allows for the record to be created once and 95 // re-used simply by having all histograms with the same ranges use the 96 // same reference. 97 mutable std::atomic<uint32_t> persistent_reference_{0}; 98 }; 99 100 } // namespace base 101 102 #endif // BASE_METRICS_BUCKET_RANGES_H_ 103