xref: /aosp_15_r20/art/libartbase/base/histogram.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2013 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBARTBASE_BASE_HISTOGRAM_H_
17*795d594fSAndroid Build Coastguard Worker #define ART_LIBARTBASE_BASE_HISTOGRAM_H_
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <string>
20*795d594fSAndroid Build Coastguard Worker #include <vector>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <android-base/macros.h>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker namespace art {
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker // Creates a data histogram  for a better understanding of statistical data.
27*795d594fSAndroid Build Coastguard Worker // Histogram analysis goes beyond simple mean and standard deviation to provide
28*795d594fSAndroid Build Coastguard Worker // percentiles values, describing where the $% of the input data lies.
29*795d594fSAndroid Build Coastguard Worker // Designed to be simple and used with timing logger in art.
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker template <class Value> class Histogram {
32*795d594fSAndroid Build Coastguard Worker   const double kAdjust;
33*795d594fSAndroid Build Coastguard Worker   const size_t kInitialBucketCount;
34*795d594fSAndroid Build Coastguard Worker 
35*795d594fSAndroid Build Coastguard Worker  public:
36*795d594fSAndroid Build Coastguard Worker   class CumulativeData {
37*795d594fSAndroid Build Coastguard Worker     friend class Histogram<Value>;
38*795d594fSAndroid Build Coastguard Worker     std::vector<uint64_t> freq_;
39*795d594fSAndroid Build Coastguard Worker     std::vector<double> perc_;
40*795d594fSAndroid Build Coastguard Worker   };
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker   // Minimum and initial number of allocated buckets in histogram.
43*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kMinBuckets = 8;
44*795d594fSAndroid Build Coastguard Worker   // Used by the cumulative timing logger to search the histogram set using for an existing split
45*795d594fSAndroid Build Coastguard Worker   // with the same name using CumulativeLogger::HistogramComparator.
46*795d594fSAndroid Build Coastguard Worker   explicit Histogram(const char* name);
47*795d594fSAndroid Build Coastguard Worker   // This is the expected constructor when creating new Histograms. Max_buckets must be even.
48*795d594fSAndroid Build Coastguard Worker   // Max_buckets, if specified, must be at least kMinBuckets.
49*795d594fSAndroid Build Coastguard Worker   Histogram(const char* name, Value initial_bucket_width, size_t max_buckets = 100);
50*795d594fSAndroid Build Coastguard Worker   void AddValue(Value);
51*795d594fSAndroid Build Coastguard Worker   void AdjustAndAddValue(Value);  // Add a value after dividing it by kAdjust.
52*795d594fSAndroid Build Coastguard Worker   // Builds the cumulative distribution function from the frequency data.
53*795d594fSAndroid Build Coastguard Worker   // Accumulative summation of frequencies.
54*795d594fSAndroid Build Coastguard Worker   // cumulative_freq[i] = sum(frequency[j] : 0 < j < i )
55*795d594fSAndroid Build Coastguard Worker   // Accumulative summation of percentiles; which is the frequency / SampleSize
56*795d594fSAndroid Build Coastguard Worker   // cumulative_perc[i] = sum(frequency[j] / SampleSize : 0 < j < i )
57*795d594fSAndroid Build Coastguard Worker   void CreateHistogram(CumulativeData* data) const;
58*795d594fSAndroid Build Coastguard Worker   // Reset the cumulative values, next time CreateHistogram is called it will recreate the cache.
59*795d594fSAndroid Build Coastguard Worker   void Reset();
60*795d594fSAndroid Build Coastguard Worker   double Mean() const;
61*795d594fSAndroid Build Coastguard Worker   double Variance() const;
62*795d594fSAndroid Build Coastguard Worker   double Percentile(double per, const CumulativeData& data) const;
63*795d594fSAndroid Build Coastguard Worker   void PrintConfidenceIntervals(std::ostream& os, double interval,
64*795d594fSAndroid Build Coastguard Worker                                 const CumulativeData& data) const;
65*795d594fSAndroid Build Coastguard Worker   void PrintMemoryUse(std::ostream& os) const;
66*795d594fSAndroid Build Coastguard Worker   void PrintBins(std::ostream& os, const CumulativeData& data) const;
67*795d594fSAndroid Build Coastguard Worker   void DumpBins(std::ostream& os) const;
68*795d594fSAndroid Build Coastguard Worker   Value GetRange(size_t bucket_idx) const;
69*795d594fSAndroid Build Coastguard Worker   size_t GetBucketCount() const;
70*795d594fSAndroid Build Coastguard Worker 
SampleSize()71*795d594fSAndroid Build Coastguard Worker   uint64_t SampleSize() const {
72*795d594fSAndroid Build Coastguard Worker     return sample_size_;
73*795d594fSAndroid Build Coastguard Worker   }
74*795d594fSAndroid Build Coastguard Worker 
Sum()75*795d594fSAndroid Build Coastguard Worker   Value Sum() const {
76*795d594fSAndroid Build Coastguard Worker     return sum_;
77*795d594fSAndroid Build Coastguard Worker   }
78*795d594fSAndroid Build Coastguard Worker 
AdjustedSum()79*795d594fSAndroid Build Coastguard Worker   Value AdjustedSum() const {
80*795d594fSAndroid Build Coastguard Worker     return sum_ * kAdjust;
81*795d594fSAndroid Build Coastguard Worker   }
82*795d594fSAndroid Build Coastguard Worker 
Min()83*795d594fSAndroid Build Coastguard Worker   Value Min() const {
84*795d594fSAndroid Build Coastguard Worker     return min_value_added_;
85*795d594fSAndroid Build Coastguard Worker   }
86*795d594fSAndroid Build Coastguard Worker 
Max()87*795d594fSAndroid Build Coastguard Worker   Value Max() const {
88*795d594fSAndroid Build Coastguard Worker     return max_value_added_;
89*795d594fSAndroid Build Coastguard Worker   }
90*795d594fSAndroid Build Coastguard Worker 
BucketWidth()91*795d594fSAndroid Build Coastguard Worker   Value BucketWidth() const {
92*795d594fSAndroid Build Coastguard Worker     return bucket_width_;
93*795d594fSAndroid Build Coastguard Worker   }
94*795d594fSAndroid Build Coastguard Worker 
Name()95*795d594fSAndroid Build Coastguard Worker   const std::string& Name() const {
96*795d594fSAndroid Build Coastguard Worker     return name_;
97*795d594fSAndroid Build Coastguard Worker   }
98*795d594fSAndroid Build Coastguard Worker 
99*795d594fSAndroid Build Coastguard Worker  private:
100*795d594fSAndroid Build Coastguard Worker   void Initialize();
101*795d594fSAndroid Build Coastguard Worker   size_t FindBucket(Value val) const;
102*795d594fSAndroid Build Coastguard Worker   void BucketiseValue(Value val);
103*795d594fSAndroid Build Coastguard Worker   // Add more buckets to the histogram to fill in a new value that exceeded
104*795d594fSAndroid Build Coastguard Worker   // the max_read_value_.
105*795d594fSAndroid Build Coastguard Worker   void GrowBuckets(Value val);
106*795d594fSAndroid Build Coastguard Worker   std::string name_;
107*795d594fSAndroid Build Coastguard Worker   // Maximum number of buckets.
108*795d594fSAndroid Build Coastguard Worker   const size_t max_buckets_;
109*795d594fSAndroid Build Coastguard Worker   // Number of samples placed in histogram.
110*795d594fSAndroid Build Coastguard Worker   size_t sample_size_;
111*795d594fSAndroid Build Coastguard Worker   // Width of the bucket range. The lower the value is the more accurate
112*795d594fSAndroid Build Coastguard Worker   // histogram percentiles are. Grows adaptively when we hit max buckets.
113*795d594fSAndroid Build Coastguard Worker   Value bucket_width_;
114*795d594fSAndroid Build Coastguard Worker   // How many occurrences of values fall within a bucket at index i where i covers the range
115*795d594fSAndroid Build Coastguard Worker   // starting at  min_ + i * bucket_width_ with size bucket_size_.
116*795d594fSAndroid Build Coastguard Worker   std::vector<uint32_t> frequency_;
117*795d594fSAndroid Build Coastguard Worker   // Summation of all the elements inputed by the user.
118*795d594fSAndroid Build Coastguard Worker   Value sum_;
119*795d594fSAndroid Build Coastguard Worker   // Minimum value that can fit in the histogram. Fixed to zero for now.
120*795d594fSAndroid Build Coastguard Worker   Value min_;
121*795d594fSAndroid Build Coastguard Worker   // Maximum value that can fit in the histogram, grows adaptively.
122*795d594fSAndroid Build Coastguard Worker   Value max_;
123*795d594fSAndroid Build Coastguard Worker   // Summation of the values entered. Used to calculate variance.
124*795d594fSAndroid Build Coastguard Worker   Value sum_of_squares_;
125*795d594fSAndroid Build Coastguard Worker   // Maximum value entered in the histogram.
126*795d594fSAndroid Build Coastguard Worker   Value min_value_added_;
127*795d594fSAndroid Build Coastguard Worker   // Minimum value entered in the histogram.
128*795d594fSAndroid Build Coastguard Worker   Value max_value_added_;
129*795d594fSAndroid Build Coastguard Worker 
130*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(Histogram);
131*795d594fSAndroid Build Coastguard Worker };
132*795d594fSAndroid Build Coastguard Worker }  // namespace art
133*795d594fSAndroid Build Coastguard Worker 
134*795d594fSAndroid Build Coastguard Worker #endif  // ART_LIBARTBASE_BASE_HISTOGRAM_H_
135