xref: /aosp_15_r20/external/libchrome/base/metrics/sample_map.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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