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