| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/metrics/sample_vector.h" | 5 #include "base/metrics/sample_vector.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/metrics/bucket_ranges.h" | 8 #include "base/metrics/bucket_ranges.h" |
| 9 | 9 |
| 10 namespace base { | 10 namespace base { |
| 11 | 11 |
| 12 typedef HistogramBase::Count Count; | 12 typedef HistogramBase::Count Count; |
| 13 typedef HistogramBase::Sample Sample; | 13 typedef HistogramBase::Sample Sample; |
| 14 | 14 |
| 15 SampleVector::SampleVector(const BucketRanges* bucket_ranges) | 15 SampleVector::SampleVector(const BucketRanges* bucket_ranges) |
| 16 : counts_(bucket_ranges->bucket_count()), | 16 : SampleVector(0, bucket_ranges) {} |
| 17 |
| 18 SampleVector::SampleVector(uint64_t id, const BucketRanges* bucket_ranges) |
| 19 : HistogramSamples(id), |
| 20 local_counts_(bucket_ranges->bucket_count()), |
| 21 counts_(&local_counts_[0]), |
| 22 counts_size_(local_counts_.size()), |
| 17 bucket_ranges_(bucket_ranges) { | 23 bucket_ranges_(bucket_ranges) { |
| 18 CHECK_GE(bucket_ranges_->bucket_count(), 1u); | 24 CHECK_GE(bucket_ranges_->bucket_count(), 1u); |
| 19 } | 25 } |
| 20 | 26 |
| 27 SampleVector::SampleVector(uint64_t id, |
| 28 HistogramBase::AtomicCount* counts, |
| 29 size_t counts_size, |
| 30 Metadata* meta, |
| 31 const BucketRanges* bucket_ranges) |
| 32 : HistogramSamples(id, meta), |
| 33 counts_(counts), |
| 34 counts_size_(bucket_ranges->bucket_count()), |
| 35 bucket_ranges_(bucket_ranges) { |
| 36 CHECK_LE(bucket_ranges_->bucket_count(), counts_size_); |
| 37 CHECK_GE(bucket_ranges_->bucket_count(), 1u); |
| 38 } |
| 39 |
| 21 SampleVector::~SampleVector() {} | 40 SampleVector::~SampleVector() {} |
| 22 | 41 |
| 23 void SampleVector::Accumulate(Sample value, Count count) { | 42 void SampleVector::Accumulate(Sample value, Count count) { |
| 24 size_t bucket_index = GetBucketIndex(value); | 43 size_t bucket_index = GetBucketIndex(value); |
| 25 subtle::NoBarrier_Store(&counts_[bucket_index], | 44 subtle::NoBarrier_Store(&counts_[bucket_index], |
| 26 subtle::NoBarrier_Load(&counts_[bucket_index]) + count); | 45 subtle::NoBarrier_Load(&counts_[bucket_index]) + count); |
| 27 IncreaseSum(count * value); | 46 IncreaseSum(count * value); |
| 28 IncreaseRedundantCount(count); | 47 IncreaseRedundantCount(count); |
| 29 } | 48 } |
| 30 | 49 |
| 31 Count SampleVector::GetCount(Sample value) const { | 50 Count SampleVector::GetCount(Sample value) const { |
| 32 size_t bucket_index = GetBucketIndex(value); | 51 size_t bucket_index = GetBucketIndex(value); |
| 33 return subtle::NoBarrier_Load(&counts_[bucket_index]); | 52 return subtle::NoBarrier_Load(&counts_[bucket_index]); |
| 34 } | 53 } |
| 35 | 54 |
| 36 Count SampleVector::TotalCount() const { | 55 Count SampleVector::TotalCount() const { |
| 37 Count count = 0; | 56 Count count = 0; |
| 38 for (size_t i = 0; i < counts_.size(); i++) { | 57 for (size_t i = 0; i < counts_size_; i++) { |
| 39 count += subtle::NoBarrier_Load(&counts_[i]); | 58 count += subtle::NoBarrier_Load(&counts_[i]); |
| 40 } | 59 } |
| 41 return count; | 60 return count; |
| 42 } | 61 } |
| 43 | 62 |
| 44 Count SampleVector::GetCountAtIndex(size_t bucket_index) const { | 63 Count SampleVector::GetCountAtIndex(size_t bucket_index) const { |
| 45 DCHECK(bucket_index < counts_.size()); | 64 DCHECK(bucket_index < counts_size_); |
| 46 return subtle::NoBarrier_Load(&counts_[bucket_index]); | 65 return subtle::NoBarrier_Load(&counts_[bucket_index]); |
| 47 } | 66 } |
| 48 | 67 |
| 49 scoped_ptr<SampleCountIterator> SampleVector::Iterator() const { | 68 scoped_ptr<SampleCountIterator> SampleVector::Iterator() const { |
| 50 return scoped_ptr<SampleCountIterator>( | 69 return scoped_ptr<SampleCountIterator>( |
| 51 new SampleVectorIterator(&counts_, bucket_ranges_)); | 70 new SampleVectorIterator(counts_, counts_size_, bucket_ranges_)); |
| 52 } | 71 } |
| 53 | 72 |
| 54 bool SampleVector::AddSubtractImpl(SampleCountIterator* iter, | 73 bool SampleVector::AddSubtractImpl(SampleCountIterator* iter, |
| 55 HistogramSamples::Operator op) { | 74 HistogramSamples::Operator op) { |
| 56 HistogramBase::Sample min; | 75 HistogramBase::Sample min; |
| 57 HistogramBase::Sample max; | 76 HistogramBase::Sample max; |
| 58 HistogramBase::Count count; | 77 HistogramBase::Count count; |
| 59 | 78 |
| 60 // Go through the iterator and add the counts into correct bucket. | 79 // Go through the iterator and add the counts into correct bucket. |
| 61 size_t index = 0; | 80 size_t index = 0; |
| 62 while (index < counts_.size() && !iter->Done()) { | 81 while (index < counts_size_ && !iter->Done()) { |
| 63 iter->Get(&min, &max, &count); | 82 iter->Get(&min, &max, &count); |
| 64 if (min == bucket_ranges_->range(index) && | 83 if (min == bucket_ranges_->range(index) && |
| 65 max == bucket_ranges_->range(index + 1)) { | 84 max == bucket_ranges_->range(index + 1)) { |
| 66 // Sample matches this bucket! | 85 // Sample matches this bucket! |
| 67 HistogramBase::Count old_counts = | 86 HistogramBase::Count old_counts = |
| 68 subtle::NoBarrier_Load(&counts_[index]); | 87 subtle::NoBarrier_Load(&counts_[index]); |
| 69 subtle::NoBarrier_Store(&counts_[index], | 88 subtle::NoBarrier_Store(&counts_[index], |
| 70 old_counts + ((op == HistogramSamples::ADD) ? count : -count)); | 89 old_counts + ((op == HistogramSamples::ADD) ? count : -count)); |
| 71 iter->Next(); | 90 iter->Next(); |
| 72 } else if (min > bucket_ranges_->range(index)) { | 91 } else if (min > bucket_ranges_->range(index)) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 102 under = mid; | 121 under = mid; |
| 103 else | 122 else |
| 104 over = mid; | 123 over = mid; |
| 105 } while (true); | 124 } while (true); |
| 106 | 125 |
| 107 DCHECK_LE(bucket_ranges_->range(mid), value); | 126 DCHECK_LE(bucket_ranges_->range(mid), value); |
| 108 CHECK_GT(bucket_ranges_->range(mid + 1), value); | 127 CHECK_GT(bucket_ranges_->range(mid + 1), value); |
| 109 return mid; | 128 return mid; |
| 110 } | 129 } |
| 111 | 130 |
| 112 SampleVectorIterator::SampleVectorIterator(const std::vector<Count>* counts, | 131 SampleVectorIterator::SampleVectorIterator( |
| 113 const BucketRanges* bucket_ranges) | 132 const std::vector<HistogramBase::AtomicCount>* counts, |
| 114 : counts_(counts), | 133 const BucketRanges* bucket_ranges) |
| 134 : counts_(&(*counts)[0]), |
| 135 counts_size_(counts->size()), |
| 115 bucket_ranges_(bucket_ranges), | 136 bucket_ranges_(bucket_ranges), |
| 116 index_(0) { | 137 index_(0) { |
| 117 CHECK_GE(bucket_ranges_->bucket_count(), counts_->size()); | 138 CHECK_GE(bucket_ranges_->bucket_count(), counts_size_); |
| 139 SkipEmptyBuckets(); |
| 140 } |
| 141 |
| 142 SampleVectorIterator::SampleVectorIterator( |
| 143 const HistogramBase::AtomicCount* counts, |
| 144 size_t counts_size, |
| 145 const BucketRanges* bucket_ranges) |
| 146 : counts_(counts), |
| 147 counts_size_(counts_size), |
| 148 bucket_ranges_(bucket_ranges), |
| 149 index_(0) { |
| 150 CHECK_GE(bucket_ranges_->bucket_count(), counts_size_); |
| 118 SkipEmptyBuckets(); | 151 SkipEmptyBuckets(); |
| 119 } | 152 } |
| 120 | 153 |
| 121 SampleVectorIterator::~SampleVectorIterator() {} | 154 SampleVectorIterator::~SampleVectorIterator() {} |
| 122 | 155 |
| 123 bool SampleVectorIterator::Done() const { | 156 bool SampleVectorIterator::Done() const { |
| 124 return index_ >= counts_->size(); | 157 return index_ >= counts_size_; |
| 125 } | 158 } |
| 126 | 159 |
| 127 void SampleVectorIterator::Next() { | 160 void SampleVectorIterator::Next() { |
| 128 DCHECK(!Done()); | 161 DCHECK(!Done()); |
| 129 index_++; | 162 index_++; |
| 130 SkipEmptyBuckets(); | 163 SkipEmptyBuckets(); |
| 131 } | 164 } |
| 132 | 165 |
| 133 void SampleVectorIterator::Get(HistogramBase::Sample* min, | 166 void SampleVectorIterator::Get(HistogramBase::Sample* min, |
| 134 HistogramBase::Sample* max, | 167 HistogramBase::Sample* max, |
| 135 HistogramBase::Count* count) const { | 168 HistogramBase::Count* count) const { |
| 136 DCHECK(!Done()); | 169 DCHECK(!Done()); |
| 137 if (min != NULL) | 170 if (min != NULL) |
| 138 *min = bucket_ranges_->range(index_); | 171 *min = bucket_ranges_->range(index_); |
| 139 if (max != NULL) | 172 if (max != NULL) |
| 140 *max = bucket_ranges_->range(index_ + 1); | 173 *max = bucket_ranges_->range(index_ + 1); |
| 141 if (count != NULL) | 174 if (count != NULL) |
| 142 *count = subtle::NoBarrier_Load(&(*counts_)[index_]); | 175 *count = subtle::NoBarrier_Load(&counts_[index_]); |
| 143 } | 176 } |
| 144 | 177 |
| 145 bool SampleVectorIterator::GetBucketIndex(size_t* index) const { | 178 bool SampleVectorIterator::GetBucketIndex(size_t* index) const { |
| 146 DCHECK(!Done()); | 179 DCHECK(!Done()); |
| 147 if (index != NULL) | 180 if (index != NULL) |
| 148 *index = index_; | 181 *index = index_; |
| 149 return true; | 182 return true; |
| 150 } | 183 } |
| 151 | 184 |
| 152 void SampleVectorIterator::SkipEmptyBuckets() { | 185 void SampleVectorIterator::SkipEmptyBuckets() { |
| 153 if (Done()) | 186 if (Done()) |
| 154 return; | 187 return; |
| 155 | 188 |
| 156 while (index_ < counts_->size()) { | 189 while (index_ < counts_size_) { |
| 157 if (subtle::NoBarrier_Load(&(*counts_)[index_]) != 0) | 190 if (subtle::NoBarrier_Load(&counts_[index_]) != 0) |
| 158 return; | 191 return; |
| 159 index_++; | 192 index_++; |
| 160 } | 193 } |
| 161 } | 194 } |
| 162 | 195 |
| 163 } // namespace base | 196 } // namespace base |
| OLD | NEW |