sample_vector.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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 <memory>
  11. #include <vector>
  12. #include "base/atomicops.h"
  13. #include "base/compiler_specific.h"
  14. #include "base/gtest_prod_util.h"
  15. #include "base/metrics/bucket_ranges.h"
  16. #include "base/metrics/histogram_base.h"
  17. #include "base/metrics/histogram_samples.h"
  18. #include "base/metrics/persistent_memory_allocator.h"
  19. namespace base {
  20. class BucketRanges;
  21. class BASE_EXPORT SampleVectorBase : public HistogramSamples {
  22. public:
  23. SampleVectorBase(uint64_t id,
  24. Metadata* meta,
  25. const BucketRanges* bucket_ranges);
  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. bool AddSubtractImpl(
  41. SampleCountIterator* iter,
  42. HistogramSamples::Operator op) override; // |op| is ADD or SUBTRACT.
  43. virtual size_t GetBucketIndex(HistogramBase::Sample value) const;
  44. // Moves the single-sample value to a mounted "counts" array.
  45. void MoveSingleSampleToCounts();
  46. // Mounts (creating if necessary) an array of "counts" for multi-value
  47. // storage.
  48. void MountCountsStorageAndMoveSingleSample();
  49. // Mounts "counts" storage that already exists. This does not attempt to move
  50. // any single-sample information to that storage as that would violate the
  51. // "const" restriction that is often used to indicate read-only memory.
  52. virtual bool MountExistingCountsStorage() const = 0;
  53. // Creates "counts" storage and returns a pointer to it. Ownership of the
  54. // array remains with the called method but will never change. This must be
  55. // called while some sort of lock is held to prevent reentry.
  56. virtual HistogramBase::Count* CreateCountsStorageWhileLocked() = 0;
  57. HistogramBase::AtomicCount* counts() {
  58. return reinterpret_cast<HistogramBase::AtomicCount*>(
  59. subtle::Acquire_Load(&counts_));
  60. }
  61. const HistogramBase::AtomicCount* counts() const {
  62. return reinterpret_cast<HistogramBase::AtomicCount*>(
  63. subtle::Acquire_Load(&counts_));
  64. }
  65. void set_counts(const HistogramBase::AtomicCount* counts) const {
  66. subtle::Release_Store(&counts_, reinterpret_cast<uintptr_t>(counts));
  67. }
  68. size_t counts_size() const { return bucket_ranges_->bucket_count(); }
  69. private:
  70. friend class SampleVectorTest;
  71. FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts);
  72. FRIEND_TEST_ALL_PREFIXES(SharedHistogramTest, CorruptSampleCounts);
  73. // |counts_| is actually a pointer to a HistogramBase::AtomicCount array but
  74. // is held as an AtomicWord for concurrency reasons. When combined with the
  75. // single_sample held in the metadata, there are four possible states:
  76. // 1) single_sample == zero, counts_ == null
  77. // 2) single_sample != zero, counts_ == null
  78. // 3) single_sample != zero, counts_ != null BUT IS EMPTY
  79. // 4) single_sample == zero, counts_ != null and may have data
  80. // Once |counts_| is set, it can never revert and any existing single-sample
  81. // must be moved to this storage. It is mutable because changing it doesn't
  82. // change the (const) data but must adapt if a non-const object causes the
  83. // storage to be allocated and updated.
  84. mutable subtle::AtomicWord counts_ = 0;
  85. // Shares the same BucketRanges with Histogram object.
  86. const BucketRanges* const bucket_ranges_;
  87. };
  88. // A sample vector that uses local memory for the counts array.
  89. class BASE_EXPORT SampleVector : public SampleVectorBase {
  90. public:
  91. explicit SampleVector(const BucketRanges* bucket_ranges);
  92. SampleVector(uint64_t id, const BucketRanges* bucket_ranges);
  93. SampleVector(const SampleVector&) = delete;
  94. SampleVector& operator=(const SampleVector&) = delete;
  95. ~SampleVector() override;
  96. private:
  97. // SampleVectorBase:
  98. bool MountExistingCountsStorage() const override;
  99. HistogramBase::Count* CreateCountsStorageWhileLocked() override;
  100. // Simple local storage for counts.
  101. mutable std::vector<HistogramBase::AtomicCount> local_counts_;
  102. };
  103. // A sample vector that uses persistent memory for the counts array.
  104. class BASE_EXPORT PersistentSampleVector : public SampleVectorBase {
  105. public:
  106. PersistentSampleVector(uint64_t id,
  107. const BucketRanges* bucket_ranges,
  108. Metadata* meta,
  109. const DelayedPersistentAllocation& counts);
  110. PersistentSampleVector(const PersistentSampleVector&) = delete;
  111. PersistentSampleVector& operator=(const PersistentSampleVector&) = delete;
  112. ~PersistentSampleVector() override;
  113. private:
  114. // SampleVectorBase:
  115. bool MountExistingCountsStorage() const override;
  116. HistogramBase::Count* CreateCountsStorageWhileLocked() override;
  117. // Persistent storage for counts.
  118. DelayedPersistentAllocation persistent_counts_;
  119. };
  120. // An iterator for sample vectors. This could be defined privately in the .cc
  121. // file but is here for easy testing.
  122. class BASE_EXPORT SampleVectorIterator : public SampleCountIterator {
  123. public:
  124. SampleVectorIterator(const std::vector<HistogramBase::AtomicCount>* counts,
  125. const BucketRanges* bucket_ranges);
  126. SampleVectorIterator(const HistogramBase::AtomicCount* counts,
  127. size_t counts_size,
  128. const BucketRanges* bucket_ranges);
  129. ~SampleVectorIterator() override;
  130. // SampleCountIterator implementation:
  131. bool Done() const override;
  132. void Next() override;
  133. void Get(HistogramBase::Sample* min,
  134. int64_t* max,
  135. HistogramBase::Count* count) const override;
  136. // SampleVector uses predefined buckets, so iterator can return bucket index.
  137. bool GetBucketIndex(size_t* index) const override;
  138. private:
  139. void SkipEmptyBuckets();
  140. const HistogramBase::AtomicCount* counts_;
  141. size_t counts_size_;
  142. const BucketRanges* bucket_ranges_;
  143. size_t index_;
  144. };
  145. } // namespace base
  146. #endif // BASE_METRICS_SAMPLE_VECTOR_H_