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 |