sample_vector.h 6.5 KB

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