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
3 // found in the LICENSE file.
5 #include "base/metrics/sample_vector.h"
7 #include "base/logging.h"
8 #include "base/metrics/bucket_ranges.h"
14 typedef HistogramBase::Count Count
;
15 typedef HistogramBase::Sample Sample
;
17 SampleVector::SampleVector(const BucketRanges
* bucket_ranges
)
18 : counts_(bucket_ranges
->size() - 1),
19 bucket_ranges_(bucket_ranges
) {
20 CHECK_GE(bucket_ranges_
->size(), 2u);
23 SampleVector::~SampleVector() {}
25 void SampleVector::Accumulate(Sample value
, Count count
) {
26 size_t bucket_index
= GetBucketIndex(value
);
27 counts_
[bucket_index
] += count
;
28 IncreaseSum(count
* value
);
29 IncreaseRedundantCount(count
);
32 Count
SampleVector::GetCount(Sample value
) const {
33 size_t bucket_index
= GetBucketIndex(value
);
34 return counts_
[bucket_index
];
37 Count
SampleVector::TotalCount() const {
39 for (size_t i
= 0; i
< counts_
.size(); i
++) {
45 Count
SampleVector::GetCountAtIndex(size_t bucket_index
) const {
46 DCHECK(bucket_index
>= 0 && bucket_index
< counts_
.size());
47 return counts_
[bucket_index
];
50 scoped_ptr
<SampleCountIterator
> SampleVector::Iterator() const {
51 return scoped_ptr
<SampleCountIterator
>(
52 new SampleVectorIterator(&counts_
, bucket_ranges_
));
55 bool SampleVector::AddSubtractImpl(SampleCountIterator
* iter
,
56 HistogramSamples::Operator op
) {
57 HistogramBase::Sample min
;
58 HistogramBase::Sample max
;
59 HistogramBase::Count count
;
61 // Go through the iterator and add the counts into correct bucket.
63 while (index
< counts_
.size() && !iter
->Done()) {
64 iter
->Get(&min
, &max
, &count
);
65 if (min
== bucket_ranges_
->range(index
) &&
66 max
== bucket_ranges_
->range(index
+ 1)) {
67 // Sample matches this bucket!
68 counts_
[index
] += (op
== HistogramSamples::ADD
) ? count
: -count
;
70 } else if (min
> bucket_ranges_
->range(index
)) {
71 // Sample is larger than current bucket range. Try next.
74 // Sample is smaller than current bucket range. We scan buckets from
75 // smallest to largest, so the sample value must be invalid.
83 // Use simple binary search. This is very general, but there are better
84 // approaches if we knew that the buckets were linearly distributed.
85 size_t SampleVector::GetBucketIndex(Sample value
) const {
86 size_t bucket_count
= bucket_ranges_
->size() - 1;
87 CHECK_GE(bucket_count
, 1u);
88 CHECK_GE(value
, bucket_ranges_
->range(0));
89 CHECK_LT(value
, bucket_ranges_
->range(bucket_count
));
92 size_t over
= bucket_count
;
95 DCHECK_GE(over
, under
);
96 mid
= under
+ (over
- under
)/2;
99 if (bucket_ranges_
->range(mid
) <= value
)
105 DCHECK_LE(bucket_ranges_
->range(mid
), value
);
106 CHECK_GT(bucket_ranges_
->range(mid
+ 1), value
);
110 SampleVectorIterator::SampleVectorIterator(const vector
<Count
>* counts
,
111 const BucketRanges
* bucket_ranges
)
113 bucket_ranges_(bucket_ranges
),
115 CHECK_GT(bucket_ranges_
->size(), counts_
->size());
119 SampleVectorIterator::~SampleVectorIterator() {}
121 bool SampleVectorIterator::Done() const {
122 return index_
>= counts_
->size();
125 void SampleVectorIterator::Next() {
131 void SampleVectorIterator::Get(HistogramBase::Sample
* min
,
132 HistogramBase::Sample
* max
,
133 HistogramBase::Count
* count
) const {
136 *min
= bucket_ranges_
->range(index_
);
138 *max
= bucket_ranges_
->range(index_
+ 1);
140 *count
= (*counts_
)[index_
];
143 bool SampleVectorIterator::GetBucketIndex(size_t* index
) const {
150 void SampleVectorIterator::SkipEmptyBuckets() {
154 while (index_
< counts_
->size()) {
155 if ((*counts_
)[index_
] != 0)