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.
4
5 #include "base/metrics/sample_map.h"
6
7 #include "base/logging.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/numerics/safe_conversions.h"
10 #include "base/stl_util.h"
11
12 namespace base {
13
14 typedef HistogramBase::Count Count;
15 typedef HistogramBase::Sample Sample;
16
17 namespace {
18
19 // An iterator for going through a SampleMap. The logic here is identical
20 // to that of PersistentSampleMapIterator but with different data structures.
21 // Changes here likely need to be duplicated there.
22 class SampleMapIterator : public SampleCountIterator {
23 public:
24 typedef std::map<HistogramBase::Sample, HistogramBase::Count>
25 SampleToCountMap;
26
27 explicit SampleMapIterator(const SampleToCountMap& sample_counts);
28 ~SampleMapIterator() override;
29
30 // SampleCountIterator:
31 bool Done() const override;
32 void Next() override;
33 void Get(HistogramBase::Sample* min,
34 int64_t* max,
35 HistogramBase::Count* count) const override;
36
37 private:
38 void SkipEmptyBuckets();
39
40 SampleToCountMap::const_iterator iter_;
41 const SampleToCountMap::const_iterator end_;
42 };
43
SampleMapIterator(const SampleToCountMap & sample_counts)44 SampleMapIterator::SampleMapIterator(const SampleToCountMap& sample_counts)
45 : iter_(sample_counts.begin()),
46 end_(sample_counts.end()) {
47 SkipEmptyBuckets();
48 }
49
50 SampleMapIterator::~SampleMapIterator() = default;
51
Done() const52 bool SampleMapIterator::Done() const {
53 return iter_ == end_;
54 }
55
Next()56 void SampleMapIterator::Next() {
57 DCHECK(!Done());
58 ++iter_;
59 SkipEmptyBuckets();
60 }
61
Get(Sample * min,int64_t * max,Count * count) const62 void SampleMapIterator::Get(Sample* min, int64_t* max, Count* count) const {
63 DCHECK(!Done());
64 if (min)
65 *min = iter_->first;
66 if (max)
67 *max = strict_cast<int64_t>(iter_->first) + 1;
68 if (count)
69 *count = iter_->second;
70 }
71
SkipEmptyBuckets()72 void SampleMapIterator::SkipEmptyBuckets() {
73 while (!Done() && iter_->second == 0) {
74 ++iter_;
75 }
76 }
77
78 } // namespace
79
SampleMap()80 SampleMap::SampleMap() : SampleMap(0) {}
81
SampleMap(uint64_t id)82 SampleMap::SampleMap(uint64_t id) : HistogramSamples(id, new LocalMetadata()) {}
83
~SampleMap()84 SampleMap::~SampleMap() {
85 delete static_cast<LocalMetadata*>(meta());
86 }
87
Accumulate(Sample value,Count count)88 void SampleMap::Accumulate(Sample value, Count count) {
89 sample_counts_[value] += count;
90 IncreaseSumAndCount(strict_cast<int64_t>(count) * value, count);
91 }
92
GetCount(Sample value) const93 Count SampleMap::GetCount(Sample value) const {
94 std::map<Sample, Count>::const_iterator it = sample_counts_.find(value);
95 if (it == sample_counts_.end())
96 return 0;
97 return it->second;
98 }
99
TotalCount() const100 Count SampleMap::TotalCount() const {
101 Count count = 0;
102 for (const auto& entry : sample_counts_) {
103 count += entry.second;
104 }
105 return count;
106 }
107
Iterator() const108 std::unique_ptr<SampleCountIterator> SampleMap::Iterator() const {
109 return WrapUnique(new SampleMapIterator(sample_counts_));
110 }
111
AddSubtractImpl(SampleCountIterator * iter,Operator op)112 bool SampleMap::AddSubtractImpl(SampleCountIterator* iter, Operator op) {
113 Sample min;
114 int64_t max;
115 Count count;
116 for (; !iter->Done(); iter->Next()) {
117 iter->Get(&min, &max, &count);
118 if (strict_cast<int64_t>(min) + 1 != max)
119 return false; // SparseHistogram only supports bucket with size 1.
120
121 sample_counts_[min] += (op == HistogramSamples::ADD) ? count : -count;
122 }
123 return true;
124 }
125
126 } // namespace base
127