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