| 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/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/metrics/persistent_memory_allocator.h" | 10 #include "base/metrics/persistent_memory_allocator.h" |
| 11 #include "base/numerics/safe_conversions.h" |
| 11 #include "base/synchronization/lock.h" | 12 #include "base/synchronization/lock.h" |
| 12 #include "base/threading/platform_thread.h" | 13 #include "base/threading/platform_thread.h" |
| 13 | 14 |
| 14 // This SampleVector makes use of the single-sample embedded in the base | 15 // This SampleVector makes use of the single-sample embedded in the base |
| 15 // HistogramSamples class. If the count is non-zero then there is guaranteed | 16 // HistogramSamples class. If the count is non-zero then there is guaranteed |
| 16 // (within the bounds of "eventual consistency") to be no allocated external | 17 // (within the bounds of "eventual consistency") to be no allocated external |
| 17 // storage. Once the full counts storage is allocated, the single-sample must | 18 // storage. Once the full counts storage is allocated, the single-sample must |
| 18 // be extracted and disabled. | 19 // be extracted and disabled. |
| 19 | 20 |
| 20 namespace base { | 21 namespace base { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 return; | 55 return; |
| 55 } | 56 } |
| 56 | 57 |
| 57 // Need real storage to store both what was in the single-sample plus the | 58 // Need real storage to store both what was in the single-sample plus the |
| 58 // parameter information. | 59 // parameter information. |
| 59 MountCountsStorageAndMoveSingleSample(); | 60 MountCountsStorageAndMoveSingleSample(); |
| 60 } | 61 } |
| 61 | 62 |
| 62 // Handle the multi-sample case. | 63 // Handle the multi-sample case. |
| 63 subtle::NoBarrier_AtomicIncrement(&counts()[bucket_index], count); | 64 subtle::NoBarrier_AtomicIncrement(&counts()[bucket_index], count); |
| 64 IncreaseSumAndCount(static_cast<int64_t>(count) * value, count); | 65 IncreaseSumAndCount(strict_cast<int64_t>(count) * value, count); |
| 65 } | 66 } |
| 66 | 67 |
| 67 Count SampleVectorBase::GetCount(Sample value) const { | 68 Count SampleVectorBase::GetCount(Sample value) const { |
| 68 return GetCountAtIndex(GetBucketIndex(value)); | 69 return GetCountAtIndex(GetBucketIndex(value)); |
| 69 } | 70 } |
| 70 | 71 |
| 71 Count SampleVectorBase::TotalCount() const { | 72 Count SampleVectorBase::TotalCount() const { |
| 72 // Handle the single-sample case. | 73 // Handle the single-sample case. |
| 73 SingleSample sample = single_sample().Load(); | 74 SingleSample sample = single_sample().Load(); |
| 74 if (sample.count != 0) | 75 if (sample.count != 0) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 } | 126 } |
| 126 | 127 |
| 127 bool SampleVectorBase::AddSubtractImpl(SampleCountIterator* iter, | 128 bool SampleVectorBase::AddSubtractImpl(SampleCountIterator* iter, |
| 128 HistogramSamples::Operator op) { | 129 HistogramSamples::Operator op) { |
| 129 // Stop now if there's nothing to do. | 130 // Stop now if there's nothing to do. |
| 130 if (iter->Done()) | 131 if (iter->Done()) |
| 131 return true; | 132 return true; |
| 132 | 133 |
| 133 // Get the first value and its index. | 134 // Get the first value and its index. |
| 134 HistogramBase::Sample min; | 135 HistogramBase::Sample min; |
| 135 HistogramBase::Sample max; | 136 int64_t max; |
| 136 HistogramBase::Count count; | 137 HistogramBase::Count count; |
| 137 iter->Get(&min, &max, &count); | 138 iter->Get(&min, &max, &count); |
| 138 size_t dest_index = GetBucketIndex(min); | 139 size_t dest_index = GetBucketIndex(min); |
| 139 | 140 |
| 140 // The destination must be a superset of the source meaning that though the | 141 // The destination must be a superset of the source meaning that though the |
| 141 // incoming ranges will find an exact match, the incoming bucket-index, if | 142 // incoming ranges will find an exact match, the incoming bucket-index, if |
| 142 // it exists, may be offset from the destination bucket-index. Calculate | 143 // it exists, may be offset from the destination bucket-index. Calculate |
| 143 // that offset of the passed iterator; there are are no overflow checks | 144 // that offset of the passed iterator; there are are no overflow checks |
| 144 // because 2's compliment math will work it out in the end. | 145 // because 2's compliment math will work it out in the end. |
| 145 // | 146 // |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 return index_ >= counts_size_; | 386 return index_ >= counts_size_; |
| 386 } | 387 } |
| 387 | 388 |
| 388 void SampleVectorIterator::Next() { | 389 void SampleVectorIterator::Next() { |
| 389 DCHECK(!Done()); | 390 DCHECK(!Done()); |
| 390 index_++; | 391 index_++; |
| 391 SkipEmptyBuckets(); | 392 SkipEmptyBuckets(); |
| 392 } | 393 } |
| 393 | 394 |
| 394 void SampleVectorIterator::Get(HistogramBase::Sample* min, | 395 void SampleVectorIterator::Get(HistogramBase::Sample* min, |
| 395 HistogramBase::Sample* max, | 396 int64_t* max, |
| 396 HistogramBase::Count* count) const { | 397 HistogramBase::Count* count) const { |
| 397 DCHECK(!Done()); | 398 DCHECK(!Done()); |
| 398 if (min != NULL) | 399 if (min != NULL) |
| 399 *min = bucket_ranges_->range(index_); | 400 *min = bucket_ranges_->range(index_); |
| 400 if (max != NULL) | 401 if (max != NULL) |
| 401 *max = bucket_ranges_->range(index_ + 1); | 402 *max = strict_cast<int64_t>(bucket_ranges_->range(index_ + 1)); |
| 402 if (count != NULL) | 403 if (count != NULL) |
| 403 *count = subtle::NoBarrier_Load(&counts_[index_]); | 404 *count = subtle::NoBarrier_Load(&counts_[index_]); |
| 404 } | 405 } |
| 405 | 406 |
| 406 bool SampleVectorIterator::GetBucketIndex(size_t* index) const { | 407 bool SampleVectorIterator::GetBucketIndex(size_t* index) const { |
| 407 DCHECK(!Done()); | 408 DCHECK(!Done()); |
| 408 if (index != NULL) | 409 if (index != NULL) |
| 409 *index = index_; | 410 *index = index_; |
| 410 return true; | 411 return true; |
| 411 } | 412 } |
| 412 | 413 |
| 413 void SampleVectorIterator::SkipEmptyBuckets() { | 414 void SampleVectorIterator::SkipEmptyBuckets() { |
| 414 if (Done()) | 415 if (Done()) |
| 415 return; | 416 return; |
| 416 | 417 |
| 417 while (index_ < counts_size_) { | 418 while (index_ < counts_size_) { |
| 418 if (subtle::NoBarrier_Load(&counts_[index_]) != 0) | 419 if (subtle::NoBarrier_Load(&counts_[index_]) != 0) |
| 419 return; | 420 return; |
| 420 index_++; | 421 index_++; |
| 421 } | 422 } |
| 422 } | 423 } |
| 423 | 424 |
| 424 } // namespace base | 425 } // namespace base |
| OLD | NEW |