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