sample_vector.h 7.6 KB

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