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