@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
// found in the LICENSE file. See the AUTHORS file for names of contributors.
# include <cassert>
# include <math.h>
# include <math.h>
# include <stdio.h>
# include <stdio.h>
# include "port/port.h"
# include "port/port.h"
@ -9,7 +10,10 @@
namespace leveldb {
namespace leveldb {
const double Histogram : : kBucketLimit [ kNumBuckets ] = {
HistogramBucketMapper : : HistogramBucketMapper ( ) :
// Add newer bucket index here.
// Should be alwyas added in sorted order.
bucketValues_ ( {
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 12 , 14 , 16 , 18 , 20 , 25 , 30 , 35 , 40 , 45 ,
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 12 , 14 , 16 , 18 , 20 , 25 , 30 , 35 , 40 , 45 ,
50 , 60 , 70 , 80 , 90 , 100 , 120 , 140 , 160 , 180 , 200 , 250 , 300 , 350 , 400 , 450 ,
50 , 60 , 70 , 80 , 90 , 100 , 120 , 140 , 160 , 180 , 200 , 250 , 300 , 350 , 400 , 450 ,
500 , 600 , 700 , 800 , 900 , 1000 , 1200 , 1400 , 1600 , 1800 , 2000 , 2500 , 3000 ,
500 , 600 , 700 , 800 , 900 , 1000 , 1200 , 1400 , 1600 , 1800 , 2000 , 2500 , 3000 ,
@ -24,30 +28,50 @@ const double Histogram::kBucketLimit[kNumBuckets] = {
70000000 , 80000000 , 90000000 , 100000000 , 120000000 , 140000000 , 160000000 ,
70000000 , 80000000 , 90000000 , 100000000 , 120000000 , 140000000 , 160000000 ,
180000000 , 200000000 , 250000000 , 300000000 , 350000000 , 400000000 ,
180000000 , 200000000 , 250000000 , 300000000 , 350000000 , 400000000 ,
450000000 , 500000000 , 600000000 , 700000000 , 800000000 , 900000000 ,
450000000 , 500000000 , 600000000 , 700000000 , 800000000 , 900000000 ,
1000000000 , 1200000000 , 1400000000 , 1600000000 , 1800000000 , 2000000000 ,
1000000000 } ) ,
2500000000.0 , 3000000000.0 , 3500000000.0 , 4000000000.0 , 4500000000.0 ,
maxBucketValue_ ( bucketValues_ . back ( ) ) ,
5000000000.0 , 6000000000.0 , 7000000000.0 , 8000000000.0 , 9000000000.0 ,
minBucketValue_ ( bucketValues_ . front ( ) ) {
1e200 ,
for ( size_t i = 0 ; i < bucketValues_ . size ( ) ; + + i ) {
} ;
valueIndexMap_ [ bucketValues_ [ i ] ] = i ;
}
}
const size_t HistogramBucketMapper : : IndexForValue ( const uint64_t value ) const {
if ( value > = maxBucketValue_ ) {
return bucketValues_ . size ( ) - 1 ;
} else if ( value > = minBucketValue_ ) {
std : : map < uint64_t , uint64_t > : : const_iterator lowerBound =
valueIndexMap_ . lower_bound ( value ) ;
if ( lowerBound ! = valueIndexMap_ . end ( ) ) {
return lowerBound - > second ;
} else {
return 0 ;
}
} else {
return 0 ;
}
}
namespace {
const HistogramBucketMapper bucketMapper ;
}
Histogram : : Histogram ( ) :
buckets_ ( std : : vector < uint64_t > ( bucketMapper . BucketCount ( ) , 0 ) ) { }
void Histogram : : Clear ( ) {
void Histogram : : Clear ( ) {
min_ = kBucketLimit [ kNumBuckets - 1 ] ;
min_ = bucketMapper . LastValue ( ) ;
max_ = 0 ;
max_ = 0 ;
num_ = 0 ;
num_ = 0 ;
sum_ = 0 ;
sum_ = 0 ;
sum_squares_ = 0 ;
sum_squares_ = 0 ;
for ( int i = 0 ; i < kNumBuckets ; i + + ) {
buckets_ . resize ( bucketMapper . BucketCount ( ) , 0 ) ;
buckets_ [ i ] = 0 ;
}
}
}
void Histogram : : Add ( double value ) {
void Histogram : : Add ( uint64_t value ) {
// Linear search is fast enough for our usage in db_bench
const size_t index = bucketMapper . IndexForValue ( value ) ;
int b = 0 ;
buckets_ [ index ] + = 1 ;
while ( b < kNumBuckets - 1 & & kBucketLimit [ b ] < = value ) {
b + + ;
}
buckets_ [ b ] + = 1.0 ;
if ( min_ > value ) min_ = value ;
if ( min_ > value ) min_ = value ;
if ( max_ < value ) max_ = value ;
if ( max_ < value ) max_ = value ;
num_ + + ;
num_ + + ;
@ -55,13 +79,17 @@ void Histogram::Add(double value) {
sum_squares_ + = ( value * value ) ;
sum_squares_ + = ( value * value ) ;
}
}
void Histogram : : Add ( double value ) {
Add ( static_cast < uint64_t > ( value ) ) ;
}
void Histogram : : Merge ( const Histogram & other ) {
void Histogram : : Merge ( const Histogram & other ) {
if ( other . min_ < min_ ) min_ = other . min_ ;
if ( other . min_ < min_ ) min_ = other . min_ ;
if ( other . max_ > max_ ) max_ = other . max_ ;
if ( other . max_ > max_ ) max_ = other . max_ ;
num_ + = other . num_ ;
num_ + = other . num_ ;
sum_ + = other . sum_ ;
sum_ + = other . sum_ ;
sum_squares_ + = other . sum_squares_ ;
sum_squares_ + = other . sum_squares_ ;
for ( int b = 0 ; b < kNumBuckets ; b + + ) {
for ( int b = 0 ; b < bucketMapper . BucketCount ( ) ; b + + ) {
buckets_ [ b ] + = other . buckets_ [ b ] ;
buckets_ [ b ] + = other . buckets_ [ b ] ;
}
}
}
}
@ -73,15 +101,19 @@ double Histogram::Median() const {
double Histogram : : Percentile ( double p ) const {
double Histogram : : Percentile ( double p ) const {
double threshold = num_ * ( p / 100.0 ) ;
double threshold = num_ * ( p / 100.0 ) ;
double sum = 0 ;
double sum = 0 ;
for ( int b = 0 ; b < kNumBuckets ; b + + ) {
for ( int b = 0 ; b < bucketMapper . BucketCount ( ) ; b + + ) {
sum + = buckets_ [ b ] ;
sum + = buckets_ [ b ] ;
if ( sum > = threshold ) {
if ( sum > = threshold ) {
// Scale linearly within this bucket
// Scale linearly within this bucket
double left_point = ( b = = 0 ) ? 0 : kBucketLimit [ b - 1 ] ;
double left_point = ( b = = 0 ) ? 0 : bucketMapper . BucketLimit ( b - 1 ) ;
double right_point = kBucketLimit [ b ] ;
double right_point = bucketMapper . BucketLimit ( b ) ;
double left_sum = sum - buckets_ [ b ] ;
double left_sum = sum - buckets_ [ b ] ;
double right_sum = sum ;
double right_sum = sum ;
double pos = ( threshold - left_sum ) / ( right_sum - left_sum ) ;
double pos = 0 ;
double right_left_diff = right_sum - left_sum ;
if ( right_left_diff ! = 0 ) {
pos = ( threshold - left_sum ) / ( right_sum - left_sum ) ;
}
double r = left_point + ( right_point - left_point ) * pos ;
double r = left_point + ( right_point - left_point ) * pos ;
if ( r < min_ ) r = min_ ;
if ( r < min_ ) r = min_ ;
if ( r > max_ ) r = max_ ;
if ( r > max_ ) r = max_ ;
@ -116,16 +148,16 @@ std::string Histogram::ToString() const {
r . append ( " ------------------------------------------------------ \n " ) ;
r . append ( " ------------------------------------------------------ \n " ) ;
const double mult = 100.0 / num_ ;
const double mult = 100.0 / num_ ;
double sum = 0 ;
double sum = 0 ;
for ( int b = 0 ; b < kNumBuckets ; b + + ) {
for ( int b = 0 ; b < bucketMapper . BucketCount ( ) ; b + + ) {
if ( buckets_ [ b ] < = 0.0 ) continue ;
if ( buckets_ [ b ] < = 0.0 ) continue ;
sum + = buckets_ [ b ] ;
sum + = buckets_ [ b ] ;
snprintf ( buf , sizeof ( buf ) ,
snprintf ( buf , sizeof ( buf ) ,
" [ %7.0f, %7.0f ) %7.0f %7.3f%% %7.3f%% " ,
" [ %ld, %ld ) %ld %7.3f%% %7.3f%% " ,
( ( b = = 0 ) ? 0.0 : kBucketLimit [ b - 1 ] ) , // left
( ( b = = 0 ) ? 0 : bucketMapper . BucketLimit ( b - 1 ) ) , // left
kBucketLimit [ b ] , // right
bucketMapper . BucketLimit ( b ) , // right
buckets_ [ b ] , // count
buckets_ [ b ] , // count
mult * buckets_ [ b ] , // percentage
mult * buckets_ [ b ] , // percentage
mult * sum ) ; // cumulative percentage
mult * sum ) ; // cumulative percentage
r . append ( buf ) ;
r . append ( buf ) ;
// Add hash marks based on percentage; 20 marks for 100%.
// Add hash marks based on percentage; 20 marks for 100%.