xref: /aosp_15_r20/external/leveldb/util/histogram.cc (revision 9507f98c5f32dee4b5f9e4a38cd499f3ff5c4490)
1*9507f98cSAndroid Build Coastguard Worker // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2*9507f98cSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*9507f98cSAndroid Build Coastguard Worker // found in the LICENSE file. See the AUTHORS file for names of contributors.
4*9507f98cSAndroid Build Coastguard Worker 
5*9507f98cSAndroid Build Coastguard Worker #include "util/histogram.h"
6*9507f98cSAndroid Build Coastguard Worker 
7*9507f98cSAndroid Build Coastguard Worker #include <cmath>
8*9507f98cSAndroid Build Coastguard Worker #include <cstdio>
9*9507f98cSAndroid Build Coastguard Worker 
10*9507f98cSAndroid Build Coastguard Worker #include "port/port.h"
11*9507f98cSAndroid Build Coastguard Worker 
12*9507f98cSAndroid Build Coastguard Worker namespace leveldb {
13*9507f98cSAndroid Build Coastguard Worker 
14*9507f98cSAndroid Build Coastguard Worker const double Histogram::kBucketLimit[kNumBuckets] = {
15*9507f98cSAndroid Build Coastguard Worker     1,
16*9507f98cSAndroid Build Coastguard Worker     2,
17*9507f98cSAndroid Build Coastguard Worker     3,
18*9507f98cSAndroid Build Coastguard Worker     4,
19*9507f98cSAndroid Build Coastguard Worker     5,
20*9507f98cSAndroid Build Coastguard Worker     6,
21*9507f98cSAndroid Build Coastguard Worker     7,
22*9507f98cSAndroid Build Coastguard Worker     8,
23*9507f98cSAndroid Build Coastguard Worker     9,
24*9507f98cSAndroid Build Coastguard Worker     10,
25*9507f98cSAndroid Build Coastguard Worker     12,
26*9507f98cSAndroid Build Coastguard Worker     14,
27*9507f98cSAndroid Build Coastguard Worker     16,
28*9507f98cSAndroid Build Coastguard Worker     18,
29*9507f98cSAndroid Build Coastguard Worker     20,
30*9507f98cSAndroid Build Coastguard Worker     25,
31*9507f98cSAndroid Build Coastguard Worker     30,
32*9507f98cSAndroid Build Coastguard Worker     35,
33*9507f98cSAndroid Build Coastguard Worker     40,
34*9507f98cSAndroid Build Coastguard Worker     45,
35*9507f98cSAndroid Build Coastguard Worker     50,
36*9507f98cSAndroid Build Coastguard Worker     60,
37*9507f98cSAndroid Build Coastguard Worker     70,
38*9507f98cSAndroid Build Coastguard Worker     80,
39*9507f98cSAndroid Build Coastguard Worker     90,
40*9507f98cSAndroid Build Coastguard Worker     100,
41*9507f98cSAndroid Build Coastguard Worker     120,
42*9507f98cSAndroid Build Coastguard Worker     140,
43*9507f98cSAndroid Build Coastguard Worker     160,
44*9507f98cSAndroid Build Coastguard Worker     180,
45*9507f98cSAndroid Build Coastguard Worker     200,
46*9507f98cSAndroid Build Coastguard Worker     250,
47*9507f98cSAndroid Build Coastguard Worker     300,
48*9507f98cSAndroid Build Coastguard Worker     350,
49*9507f98cSAndroid Build Coastguard Worker     400,
50*9507f98cSAndroid Build Coastguard Worker     450,
51*9507f98cSAndroid Build Coastguard Worker     500,
52*9507f98cSAndroid Build Coastguard Worker     600,
53*9507f98cSAndroid Build Coastguard Worker     700,
54*9507f98cSAndroid Build Coastguard Worker     800,
55*9507f98cSAndroid Build Coastguard Worker     900,
56*9507f98cSAndroid Build Coastguard Worker     1000,
57*9507f98cSAndroid Build Coastguard Worker     1200,
58*9507f98cSAndroid Build Coastguard Worker     1400,
59*9507f98cSAndroid Build Coastguard Worker     1600,
60*9507f98cSAndroid Build Coastguard Worker     1800,
61*9507f98cSAndroid Build Coastguard Worker     2000,
62*9507f98cSAndroid Build Coastguard Worker     2500,
63*9507f98cSAndroid Build Coastguard Worker     3000,
64*9507f98cSAndroid Build Coastguard Worker     3500,
65*9507f98cSAndroid Build Coastguard Worker     4000,
66*9507f98cSAndroid Build Coastguard Worker     4500,
67*9507f98cSAndroid Build Coastguard Worker     5000,
68*9507f98cSAndroid Build Coastguard Worker     6000,
69*9507f98cSAndroid Build Coastguard Worker     7000,
70*9507f98cSAndroid Build Coastguard Worker     8000,
71*9507f98cSAndroid Build Coastguard Worker     9000,
72*9507f98cSAndroid Build Coastguard Worker     10000,
73*9507f98cSAndroid Build Coastguard Worker     12000,
74*9507f98cSAndroid Build Coastguard Worker     14000,
75*9507f98cSAndroid Build Coastguard Worker     16000,
76*9507f98cSAndroid Build Coastguard Worker     18000,
77*9507f98cSAndroid Build Coastguard Worker     20000,
78*9507f98cSAndroid Build Coastguard Worker     25000,
79*9507f98cSAndroid Build Coastguard Worker     30000,
80*9507f98cSAndroid Build Coastguard Worker     35000,
81*9507f98cSAndroid Build Coastguard Worker     40000,
82*9507f98cSAndroid Build Coastguard Worker     45000,
83*9507f98cSAndroid Build Coastguard Worker     50000,
84*9507f98cSAndroid Build Coastguard Worker     60000,
85*9507f98cSAndroid Build Coastguard Worker     70000,
86*9507f98cSAndroid Build Coastguard Worker     80000,
87*9507f98cSAndroid Build Coastguard Worker     90000,
88*9507f98cSAndroid Build Coastguard Worker     100000,
89*9507f98cSAndroid Build Coastguard Worker     120000,
90*9507f98cSAndroid Build Coastguard Worker     140000,
91*9507f98cSAndroid Build Coastguard Worker     160000,
92*9507f98cSAndroid Build Coastguard Worker     180000,
93*9507f98cSAndroid Build Coastguard Worker     200000,
94*9507f98cSAndroid Build Coastguard Worker     250000,
95*9507f98cSAndroid Build Coastguard Worker     300000,
96*9507f98cSAndroid Build Coastguard Worker     350000,
97*9507f98cSAndroid Build Coastguard Worker     400000,
98*9507f98cSAndroid Build Coastguard Worker     450000,
99*9507f98cSAndroid Build Coastguard Worker     500000,
100*9507f98cSAndroid Build Coastguard Worker     600000,
101*9507f98cSAndroid Build Coastguard Worker     700000,
102*9507f98cSAndroid Build Coastguard Worker     800000,
103*9507f98cSAndroid Build Coastguard Worker     900000,
104*9507f98cSAndroid Build Coastguard Worker     1000000,
105*9507f98cSAndroid Build Coastguard Worker     1200000,
106*9507f98cSAndroid Build Coastguard Worker     1400000,
107*9507f98cSAndroid Build Coastguard Worker     1600000,
108*9507f98cSAndroid Build Coastguard Worker     1800000,
109*9507f98cSAndroid Build Coastguard Worker     2000000,
110*9507f98cSAndroid Build Coastguard Worker     2500000,
111*9507f98cSAndroid Build Coastguard Worker     3000000,
112*9507f98cSAndroid Build Coastguard Worker     3500000,
113*9507f98cSAndroid Build Coastguard Worker     4000000,
114*9507f98cSAndroid Build Coastguard Worker     4500000,
115*9507f98cSAndroid Build Coastguard Worker     5000000,
116*9507f98cSAndroid Build Coastguard Worker     6000000,
117*9507f98cSAndroid Build Coastguard Worker     7000000,
118*9507f98cSAndroid Build Coastguard Worker     8000000,
119*9507f98cSAndroid Build Coastguard Worker     9000000,
120*9507f98cSAndroid Build Coastguard Worker     10000000,
121*9507f98cSAndroid Build Coastguard Worker     12000000,
122*9507f98cSAndroid Build Coastguard Worker     14000000,
123*9507f98cSAndroid Build Coastguard Worker     16000000,
124*9507f98cSAndroid Build Coastguard Worker     18000000,
125*9507f98cSAndroid Build Coastguard Worker     20000000,
126*9507f98cSAndroid Build Coastguard Worker     25000000,
127*9507f98cSAndroid Build Coastguard Worker     30000000,
128*9507f98cSAndroid Build Coastguard Worker     35000000,
129*9507f98cSAndroid Build Coastguard Worker     40000000,
130*9507f98cSAndroid Build Coastguard Worker     45000000,
131*9507f98cSAndroid Build Coastguard Worker     50000000,
132*9507f98cSAndroid Build Coastguard Worker     60000000,
133*9507f98cSAndroid Build Coastguard Worker     70000000,
134*9507f98cSAndroid Build Coastguard Worker     80000000,
135*9507f98cSAndroid Build Coastguard Worker     90000000,
136*9507f98cSAndroid Build Coastguard Worker     100000000,
137*9507f98cSAndroid Build Coastguard Worker     120000000,
138*9507f98cSAndroid Build Coastguard Worker     140000000,
139*9507f98cSAndroid Build Coastguard Worker     160000000,
140*9507f98cSAndroid Build Coastguard Worker     180000000,
141*9507f98cSAndroid Build Coastguard Worker     200000000,
142*9507f98cSAndroid Build Coastguard Worker     250000000,
143*9507f98cSAndroid Build Coastguard Worker     300000000,
144*9507f98cSAndroid Build Coastguard Worker     350000000,
145*9507f98cSAndroid Build Coastguard Worker     400000000,
146*9507f98cSAndroid Build Coastguard Worker     450000000,
147*9507f98cSAndroid Build Coastguard Worker     500000000,
148*9507f98cSAndroid Build Coastguard Worker     600000000,
149*9507f98cSAndroid Build Coastguard Worker     700000000,
150*9507f98cSAndroid Build Coastguard Worker     800000000,
151*9507f98cSAndroid Build Coastguard Worker     900000000,
152*9507f98cSAndroid Build Coastguard Worker     1000000000,
153*9507f98cSAndroid Build Coastguard Worker     1200000000,
154*9507f98cSAndroid Build Coastguard Worker     1400000000,
155*9507f98cSAndroid Build Coastguard Worker     1600000000,
156*9507f98cSAndroid Build Coastguard Worker     1800000000,
157*9507f98cSAndroid Build Coastguard Worker     2000000000,
158*9507f98cSAndroid Build Coastguard Worker     2500000000.0,
159*9507f98cSAndroid Build Coastguard Worker     3000000000.0,
160*9507f98cSAndroid Build Coastguard Worker     3500000000.0,
161*9507f98cSAndroid Build Coastguard Worker     4000000000.0,
162*9507f98cSAndroid Build Coastguard Worker     4500000000.0,
163*9507f98cSAndroid Build Coastguard Worker     5000000000.0,
164*9507f98cSAndroid Build Coastguard Worker     6000000000.0,
165*9507f98cSAndroid Build Coastguard Worker     7000000000.0,
166*9507f98cSAndroid Build Coastguard Worker     8000000000.0,
167*9507f98cSAndroid Build Coastguard Worker     9000000000.0,
168*9507f98cSAndroid Build Coastguard Worker     1e200,
169*9507f98cSAndroid Build Coastguard Worker };
170*9507f98cSAndroid Build Coastguard Worker 
Clear()171*9507f98cSAndroid Build Coastguard Worker void Histogram::Clear() {
172*9507f98cSAndroid Build Coastguard Worker   min_ = kBucketLimit[kNumBuckets - 1];
173*9507f98cSAndroid Build Coastguard Worker   max_ = 0;
174*9507f98cSAndroid Build Coastguard Worker   num_ = 0;
175*9507f98cSAndroid Build Coastguard Worker   sum_ = 0;
176*9507f98cSAndroid Build Coastguard Worker   sum_squares_ = 0;
177*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < kNumBuckets; i++) {
178*9507f98cSAndroid Build Coastguard Worker     buckets_[i] = 0;
179*9507f98cSAndroid Build Coastguard Worker   }
180*9507f98cSAndroid Build Coastguard Worker }
181*9507f98cSAndroid Build Coastguard Worker 
Add(double value)182*9507f98cSAndroid Build Coastguard Worker void Histogram::Add(double value) {
183*9507f98cSAndroid Build Coastguard Worker   // Linear search is fast enough for our usage in db_bench
184*9507f98cSAndroid Build Coastguard Worker   int b = 0;
185*9507f98cSAndroid Build Coastguard Worker   while (b < kNumBuckets - 1 && kBucketLimit[b] <= value) {
186*9507f98cSAndroid Build Coastguard Worker     b++;
187*9507f98cSAndroid Build Coastguard Worker   }
188*9507f98cSAndroid Build Coastguard Worker   buckets_[b] += 1.0;
189*9507f98cSAndroid Build Coastguard Worker   if (min_ > value) min_ = value;
190*9507f98cSAndroid Build Coastguard Worker   if (max_ < value) max_ = value;
191*9507f98cSAndroid Build Coastguard Worker   num_++;
192*9507f98cSAndroid Build Coastguard Worker   sum_ += value;
193*9507f98cSAndroid Build Coastguard Worker   sum_squares_ += (value * value);
194*9507f98cSAndroid Build Coastguard Worker }
195*9507f98cSAndroid Build Coastguard Worker 
Merge(const Histogram & other)196*9507f98cSAndroid Build Coastguard Worker void Histogram::Merge(const Histogram& other) {
197*9507f98cSAndroid Build Coastguard Worker   if (other.min_ < min_) min_ = other.min_;
198*9507f98cSAndroid Build Coastguard Worker   if (other.max_ > max_) max_ = other.max_;
199*9507f98cSAndroid Build Coastguard Worker   num_ += other.num_;
200*9507f98cSAndroid Build Coastguard Worker   sum_ += other.sum_;
201*9507f98cSAndroid Build Coastguard Worker   sum_squares_ += other.sum_squares_;
202*9507f98cSAndroid Build Coastguard Worker   for (int b = 0; b < kNumBuckets; b++) {
203*9507f98cSAndroid Build Coastguard Worker     buckets_[b] += other.buckets_[b];
204*9507f98cSAndroid Build Coastguard Worker   }
205*9507f98cSAndroid Build Coastguard Worker }
206*9507f98cSAndroid Build Coastguard Worker 
Median() const207*9507f98cSAndroid Build Coastguard Worker double Histogram::Median() const { return Percentile(50.0); }
208*9507f98cSAndroid Build Coastguard Worker 
Percentile(double p) const209*9507f98cSAndroid Build Coastguard Worker double Histogram::Percentile(double p) const {
210*9507f98cSAndroid Build Coastguard Worker   double threshold = num_ * (p / 100.0);
211*9507f98cSAndroid Build Coastguard Worker   double sum = 0;
212*9507f98cSAndroid Build Coastguard Worker   for (int b = 0; b < kNumBuckets; b++) {
213*9507f98cSAndroid Build Coastguard Worker     sum += buckets_[b];
214*9507f98cSAndroid Build Coastguard Worker     if (sum >= threshold) {
215*9507f98cSAndroid Build Coastguard Worker       // Scale linearly within this bucket
216*9507f98cSAndroid Build Coastguard Worker       double left_point = (b == 0) ? 0 : kBucketLimit[b - 1];
217*9507f98cSAndroid Build Coastguard Worker       double right_point = kBucketLimit[b];
218*9507f98cSAndroid Build Coastguard Worker       double left_sum = sum - buckets_[b];
219*9507f98cSAndroid Build Coastguard Worker       double right_sum = sum;
220*9507f98cSAndroid Build Coastguard Worker       double pos = (threshold - left_sum) / (right_sum - left_sum);
221*9507f98cSAndroid Build Coastguard Worker       double r = left_point + (right_point - left_point) * pos;
222*9507f98cSAndroid Build Coastguard Worker       if (r < min_) r = min_;
223*9507f98cSAndroid Build Coastguard Worker       if (r > max_) r = max_;
224*9507f98cSAndroid Build Coastguard Worker       return r;
225*9507f98cSAndroid Build Coastguard Worker     }
226*9507f98cSAndroid Build Coastguard Worker   }
227*9507f98cSAndroid Build Coastguard Worker   return max_;
228*9507f98cSAndroid Build Coastguard Worker }
229*9507f98cSAndroid Build Coastguard Worker 
Average() const230*9507f98cSAndroid Build Coastguard Worker double Histogram::Average() const {
231*9507f98cSAndroid Build Coastguard Worker   if (num_ == 0.0) return 0;
232*9507f98cSAndroid Build Coastguard Worker   return sum_ / num_;
233*9507f98cSAndroid Build Coastguard Worker }
234*9507f98cSAndroid Build Coastguard Worker 
StandardDeviation() const235*9507f98cSAndroid Build Coastguard Worker double Histogram::StandardDeviation() const {
236*9507f98cSAndroid Build Coastguard Worker   if (num_ == 0.0) return 0;
237*9507f98cSAndroid Build Coastguard Worker   double variance = (sum_squares_ * num_ - sum_ * sum_) / (num_ * num_);
238*9507f98cSAndroid Build Coastguard Worker   return sqrt(variance);
239*9507f98cSAndroid Build Coastguard Worker }
240*9507f98cSAndroid Build Coastguard Worker 
ToString() const241*9507f98cSAndroid Build Coastguard Worker std::string Histogram::ToString() const {
242*9507f98cSAndroid Build Coastguard Worker   std::string r;
243*9507f98cSAndroid Build Coastguard Worker   char buf[200];
244*9507f98cSAndroid Build Coastguard Worker   std::snprintf(buf, sizeof(buf), "Count: %.0f  Average: %.4f  StdDev: %.2f\n",
245*9507f98cSAndroid Build Coastguard Worker                 num_, Average(), StandardDeviation());
246*9507f98cSAndroid Build Coastguard Worker   r.append(buf);
247*9507f98cSAndroid Build Coastguard Worker   std::snprintf(buf, sizeof(buf), "Min: %.4f  Median: %.4f  Max: %.4f\n",
248*9507f98cSAndroid Build Coastguard Worker                 (num_ == 0.0 ? 0.0 : min_), Median(), max_);
249*9507f98cSAndroid Build Coastguard Worker   r.append(buf);
250*9507f98cSAndroid Build Coastguard Worker   r.append("------------------------------------------------------\n");
251*9507f98cSAndroid Build Coastguard Worker   const double mult = 100.0 / num_;
252*9507f98cSAndroid Build Coastguard Worker   double sum = 0;
253*9507f98cSAndroid Build Coastguard Worker   for (int b = 0; b < kNumBuckets; b++) {
254*9507f98cSAndroid Build Coastguard Worker     if (buckets_[b] <= 0.0) continue;
255*9507f98cSAndroid Build Coastguard Worker     sum += buckets_[b];
256*9507f98cSAndroid Build Coastguard Worker     std::snprintf(buf, sizeof(buf), "[ %7.0f, %7.0f ) %7.0f %7.3f%% %7.3f%% ",
257*9507f98cSAndroid Build Coastguard Worker                   ((b == 0) ? 0.0 : kBucketLimit[b - 1]),  // left
258*9507f98cSAndroid Build Coastguard Worker                   kBucketLimit[b],                         // right
259*9507f98cSAndroid Build Coastguard Worker                   buckets_[b],                             // count
260*9507f98cSAndroid Build Coastguard Worker                   mult * buckets_[b],                      // percentage
261*9507f98cSAndroid Build Coastguard Worker                   mult * sum);  // cumulative percentage
262*9507f98cSAndroid Build Coastguard Worker     r.append(buf);
263*9507f98cSAndroid Build Coastguard Worker 
264*9507f98cSAndroid Build Coastguard Worker     // Add hash marks based on percentage; 20 marks for 100%.
265*9507f98cSAndroid Build Coastguard Worker     int marks = static_cast<int>(20 * (buckets_[b] / num_) + 0.5);
266*9507f98cSAndroid Build Coastguard Worker     r.append(marks, '#');
267*9507f98cSAndroid Build Coastguard Worker     r.push_back('\n');
268*9507f98cSAndroid Build Coastguard Worker   }
269*9507f98cSAndroid Build Coastguard Worker   return r;
270*9507f98cSAndroid Build Coastguard Worker }
271*9507f98cSAndroid Build Coastguard Worker 
272*9507f98cSAndroid Build Coastguard Worker }  // namespace leveldb
273