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/histogram_samples.h" | 5 #include "base/metrics/histogram_samples.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/numerics/safe_conversions.h" |
10 #include "base/numerics/safe_math.h" | 11 #include "base/numerics/safe_math.h" |
11 #include "base/pickle.h" | 12 #include "base/pickle.h" |
12 | 13 |
13 namespace base { | 14 namespace base { |
14 | 15 |
15 namespace { | 16 namespace { |
16 | 17 |
17 // A shorthand constant for the max value of size_t. | 18 // A shorthand constant for the max value of size_t. |
18 constexpr size_t kSizeMax = std::numeric_limits<size_t>::max(); | 19 constexpr size_t kSizeMax = std::numeric_limits<size_t>::max(); |
19 | 20 |
20 // A constant stored in an AtomicSingleSample (as_atomic) to indicate that the | 21 // A constant stored in an AtomicSingleSample (as_atomic) to indicate that the |
21 // sample is "disabled" and no further accumulation should be done with it. The | 22 // sample is "disabled" and no further accumulation should be done with it. The |
22 // value is chosen such that it will be MAX_UINT16 for both |bucket| & |count|, | 23 // value is chosen such that it will be MAX_UINT16 for both |bucket| & |count|, |
23 // and thus less likely to conflict with real use. Conflicts are explicitly | 24 // and thus less likely to conflict with real use. Conflicts are explicitly |
24 // handled in the code but it's worth making them as unlikely as possible. | 25 // handled in the code but it's worth making them as unlikely as possible. |
25 constexpr int32_t kDisabledSingleSample = -1; | 26 constexpr int32_t kDisabledSingleSample = -1; |
26 | 27 |
27 class SampleCountPickleIterator : public SampleCountIterator { | 28 class SampleCountPickleIterator : public SampleCountIterator { |
28 public: | 29 public: |
29 explicit SampleCountPickleIterator(PickleIterator* iter); | 30 explicit SampleCountPickleIterator(PickleIterator* iter); |
30 | 31 |
31 bool Done() const override; | 32 bool Done() const override; |
32 void Next() override; | 33 void Next() override; |
33 void Get(HistogramBase::Sample* min, | 34 void Get(HistogramBase::Sample* min, |
34 HistogramBase::Sample* max, | 35 int64_t* max, |
35 HistogramBase::Count* count) const override; | 36 HistogramBase::Count* count) const override; |
36 | 37 |
37 private: | 38 private: |
38 PickleIterator* const iter_; | 39 PickleIterator* const iter_; |
39 | 40 |
40 HistogramBase::Sample min_; | 41 HistogramBase::Sample min_; |
41 HistogramBase::Sample max_; | 42 int64_t max_; |
42 HistogramBase::Count count_; | 43 HistogramBase::Count count_; |
43 bool is_done_; | 44 bool is_done_; |
44 }; | 45 }; |
45 | 46 |
46 SampleCountPickleIterator::SampleCountPickleIterator(PickleIterator* iter) | 47 SampleCountPickleIterator::SampleCountPickleIterator(PickleIterator* iter) |
47 : iter_(iter), | 48 : iter_(iter), |
48 is_done_(false) { | 49 is_done_(false) { |
49 Next(); | 50 Next(); |
50 } | 51 } |
51 | 52 |
52 bool SampleCountPickleIterator::Done() const { | 53 bool SampleCountPickleIterator::Done() const { |
53 return is_done_; | 54 return is_done_; |
54 } | 55 } |
55 | 56 |
56 void SampleCountPickleIterator::Next() { | 57 void SampleCountPickleIterator::Next() { |
57 DCHECK(!Done()); | 58 DCHECK(!Done()); |
58 if (!iter_->ReadInt(&min_) || | 59 if (!iter_->ReadInt(&min_) || !iter_->ReadInt64(&max_) || |
59 !iter_->ReadInt(&max_) || | 60 !iter_->ReadInt(&count_)) { |
60 !iter_->ReadInt(&count_)) | |
61 is_done_ = true; | 61 is_done_ = true; |
| 62 } |
62 } | 63 } |
63 | 64 |
64 void SampleCountPickleIterator::Get(HistogramBase::Sample* min, | 65 void SampleCountPickleIterator::Get(HistogramBase::Sample* min, |
65 HistogramBase::Sample* max, | 66 int64_t* max, |
66 HistogramBase::Count* count) const { | 67 HistogramBase::Count* count) const { |
67 DCHECK(!Done()); | 68 DCHECK(!Done()); |
68 *min = min_; | 69 *min = min_; |
69 *max = max_; | 70 *max = max_; |
70 *count = count_; | 71 *count = count_; |
71 } | 72 } |
72 | 73 |
73 } // namespace | 74 } // namespace |
74 | 75 |
75 static_assert(sizeof(HistogramSamples::AtomicSingleSample) == | 76 static_assert(sizeof(HistogramSamples::AtomicSingleSample) == |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 DCHECK(success); | 214 DCHECK(success); |
214 } | 215 } |
215 | 216 |
216 bool HistogramSamples::Serialize(Pickle* pickle) const { | 217 bool HistogramSamples::Serialize(Pickle* pickle) const { |
217 if (!pickle->WriteInt64(sum())) | 218 if (!pickle->WriteInt64(sum())) |
218 return false; | 219 return false; |
219 if (!pickle->WriteInt(redundant_count())) | 220 if (!pickle->WriteInt(redundant_count())) |
220 return false; | 221 return false; |
221 | 222 |
222 HistogramBase::Sample min; | 223 HistogramBase::Sample min; |
223 HistogramBase::Sample max; | 224 int64_t max; |
224 HistogramBase::Count count; | 225 HistogramBase::Count count; |
225 for (std::unique_ptr<SampleCountIterator> it = Iterator(); !it->Done(); | 226 for (std::unique_ptr<SampleCountIterator> it = Iterator(); !it->Done(); |
226 it->Next()) { | 227 it->Next()) { |
227 it->Get(&min, &max, &count); | 228 it->Get(&min, &max, &count); |
228 if (!pickle->WriteInt(min) || | 229 if (!pickle->WriteInt(min) || !pickle->WriteInt64(max) || |
229 !pickle->WriteInt(max) || | 230 !pickle->WriteInt(count)) { |
230 !pickle->WriteInt(count)) | |
231 return false; | 231 return false; |
| 232 } |
232 } | 233 } |
233 return true; | 234 return true; |
234 } | 235 } |
235 | 236 |
236 bool HistogramSamples::AccumulateSingleSample(HistogramBase::Sample value, | 237 bool HistogramSamples::AccumulateSingleSample(HistogramBase::Sample value, |
237 HistogramBase::Count count, | 238 HistogramBase::Count count, |
238 size_t bucket) { | 239 size_t bucket) { |
239 if (single_sample().Accumulate(bucket, count)) { | 240 if (single_sample().Accumulate(bucket, count)) { |
240 // Success. Update the (separate) sum and redundant-count. | 241 // Success. Update the (separate) sum and redundant-count. |
241 IncreaseSumAndCount(static_cast<int64_t>(value) * count, count); | 242 IncreaseSumAndCount(strict_cast<int64_t>(value) * count, count); |
242 return true; | 243 return true; |
243 } | 244 } |
244 return false; | 245 return false; |
245 } | 246 } |
246 | 247 |
247 void HistogramSamples::IncreaseSumAndCount(int64_t sum, | 248 void HistogramSamples::IncreaseSumAndCount(int64_t sum, |
248 HistogramBase::Count count) { | 249 HistogramBase::Count count) { |
249 #ifdef ARCH_CPU_64_BITS | 250 #ifdef ARCH_CPU_64_BITS |
250 subtle::NoBarrier_AtomicIncrement(&meta_->sum, sum); | 251 subtle::NoBarrier_AtomicIncrement(&meta_->sum, sum); |
251 #else | 252 #else |
252 meta_->sum += sum; | 253 meta_->sum += sum; |
253 #endif | 254 #endif |
254 subtle::NoBarrier_AtomicIncrement(&meta_->redundant_count, count); | 255 subtle::NoBarrier_AtomicIncrement(&meta_->redundant_count, count); |
255 } | 256 } |
256 | 257 |
257 SampleCountIterator::~SampleCountIterator() {} | 258 SampleCountIterator::~SampleCountIterator() {} |
258 | 259 |
259 bool SampleCountIterator::GetBucketIndex(size_t* index) const { | 260 bool SampleCountIterator::GetBucketIndex(size_t* index) const { |
260 DCHECK(!Done()); | 261 DCHECK(!Done()); |
261 return false; | 262 return false; |
262 } | 263 } |
263 | 264 |
264 SingleSampleIterator::SingleSampleIterator(HistogramBase::Sample min, | 265 SingleSampleIterator::SingleSampleIterator(HistogramBase::Sample min, |
265 HistogramBase::Sample max, | 266 int64_t max, |
266 HistogramBase::Count count) | 267 HistogramBase::Count count) |
267 : SingleSampleIterator(min, max, count, kSizeMax) {} | 268 : SingleSampleIterator(min, max, count, kSizeMax) {} |
268 | 269 |
269 SingleSampleIterator::SingleSampleIterator(HistogramBase::Sample min, | 270 SingleSampleIterator::SingleSampleIterator(HistogramBase::Sample min, |
270 HistogramBase::Sample max, | 271 int64_t max, |
271 HistogramBase::Count count, | 272 HistogramBase::Count count, |
272 size_t bucket_index) | 273 size_t bucket_index) |
273 : min_(min), max_(max), bucket_index_(bucket_index), count_(count) {} | 274 : min_(min), max_(max), bucket_index_(bucket_index), count_(count) {} |
274 | 275 |
275 SingleSampleIterator::~SingleSampleIterator() {} | 276 SingleSampleIterator::~SingleSampleIterator() {} |
276 | 277 |
277 bool SingleSampleIterator::Done() const { | 278 bool SingleSampleIterator::Done() const { |
278 return count_ == 0; | 279 return count_ == 0; |
279 } | 280 } |
280 | 281 |
281 void SingleSampleIterator::Next() { | 282 void SingleSampleIterator::Next() { |
282 DCHECK(!Done()); | 283 DCHECK(!Done()); |
283 count_ = 0; | 284 count_ = 0; |
284 } | 285 } |
285 | 286 |
286 void SingleSampleIterator::Get(HistogramBase::Sample* min, | 287 void SingleSampleIterator::Get(HistogramBase::Sample* min, |
287 HistogramBase::Sample* max, | 288 int64_t* max, |
288 HistogramBase::Count* count) const { | 289 HistogramBase::Count* count) const { |
289 DCHECK(!Done()); | 290 DCHECK(!Done()); |
290 if (min != nullptr) | 291 if (min != nullptr) |
291 *min = min_; | 292 *min = min_; |
292 if (max != nullptr) | 293 if (max != nullptr) |
293 *max = max_; | 294 *max = max_; |
294 if (count != nullptr) | 295 if (count != nullptr) |
295 *count = count_; | 296 *count = count_; |
296 } | 297 } |
297 | 298 |
298 bool SingleSampleIterator::GetBucketIndex(size_t* index) const { | 299 bool SingleSampleIterator::GetBucketIndex(size_t* index) const { |
299 DCHECK(!Done()); | 300 DCHECK(!Done()); |
300 if (bucket_index_ == kSizeMax) | 301 if (bucket_index_ == kSizeMax) |
301 return false; | 302 return false; |
302 *index = bucket_index_; | 303 *index = bucket_index_; |
303 return true; | 304 return true; |
304 } | 305 } |
305 | 306 |
306 } // namespace base | 307 } // namespace base |
OLD | NEW |