@@ -401,7 +401,8 @@ void Meter::clear() {
401401ReservoirSampler::ReservoirSampler (size_t sample_size)
402402 : sample_size_(sample_size) {}
403403
404- void ReservoirSampler::sample (const int64_t value) {
404+ int64_t ReservoirSampler::sample (const int64_t value) {
405+ int64_t replaced_value = 0 ;
405406 if (n_ < sample_size_) {
406407 reservoir_.push_back (value);
407408 } else {
@@ -410,12 +411,16 @@ void ReservoirSampler::sample(const int64_t value) {
410411 }
411412 size_t j = rand () % (n_ + 1 );
412413 if (j < sample_size_) {
414+ replaced_value = reservoir_[j];
413415 reservoir_[j] = value;
414416 }
415417 }
416418 n_++;
419+ return replaced_value;
417420}
418421
422+ size_t ReservoirSampler::current_size () const { return reservoir_.size (); }
423+
419424const std::vector<int64_t > ReservoirSampler::snapshot () const {
420425 return reservoir_;
421426}
@@ -426,8 +431,9 @@ void ReservoirSampler::clear() {
426431}
427432
428433HistogramStats::HistogramStats (size_t data_size, int64_t min, int64_t max,
429- double mean, double std_dev, double p50,
430- double p95, double p99)
434+ long double mean, long double std_dev,
435+ long double p50, long double p95,
436+ long double p99)
431437 : data_size_(data_size),
432438 min_(min),
433439 max_(max),
@@ -443,10 +449,21 @@ Histogram::Histogram(const std::string name, const std::string unit,
443449
444450void Histogram::insert (const int64_t value) {
445451 std::lock_guard<std::mutex> guard (sampler_lock_);
446- sampler_.sample (value);
452+ size_t old_reservoir_size = sampler_.current_size ();
453+ int64_t replaced_value = sampler_.sample (value);
454+ size_t new_reservoir_size = sampler_.current_size ();
455+ update_mean (old_reservoir_size, new_reservoir_size, value, replaced_value);
456+ }
457+
458+ void Histogram::update_mean (const size_t old_reservoir_size,
459+ const size_t new_reservoir_size,
460+ const int64_t new_value, const int64_t old_value) {
461+ int64_t old_sum = static_cast <int64_t >(mean_ * old_reservoir_size);
462+ mean_ = static_cast <long double >(old_sum - old_value + new_value) /
463+ static_cast <long double >(new_reservoir_size);
447464}
448465
449- double Histogram::percentile (std::vector<int64_t > snapshot, double rank) {
466+ long double Histogram::percentile (std::vector<int64_t > snapshot, double rank) {
450467 if (rank < 0 || rank > 1 ) {
451468 throw std::invalid_argument (" Percentile rank must be in [0,1]!" );
452469 }
@@ -468,7 +485,7 @@ double Histogram::percentile(std::vector<int64_t> snapshot, double rank) {
468485 x = sample_size;
469486 }
470487 size_t index = std::floor (x) - 1 ;
471- double v = snapshot[index];
488+ long double v = snapshot[index];
472489 double remainder = x - std::floor (x);
473490 if (remainder == 0 ) {
474491 return v;
@@ -477,7 +494,7 @@ double Histogram::percentile(std::vector<int64_t> snapshot, double rank) {
477494 }
478495}
479496
480- double Histogram::percentile (double rank) {
497+ long double Histogram::percentile (double rank) {
481498 std::lock_guard<std::mutex> guard (sampler_lock_);
482499 std::vector<int64_t > snapshot = sampler_.snapshot ();
483500 if (snapshot.size () == 0 ) {
@@ -499,22 +516,19 @@ const HistogramStats Histogram::compute_stats() {
499516 std::sort (snapshot.begin (), snapshot.end ());
500517 int64_t min = snapshot.front ();
501518 int64_t max = snapshot.back ();
502- double p50 = percentile (snapshot, .5 );
503- double p95 = percentile (snapshot, .95 );
504- double p99 = percentile (snapshot, .99 );
505- double mean = static_cast <double >(
506- std::accumulate (snapshot.begin (), snapshot.end (), 0 )) /
507- static_cast <double >(snapshot_size);
508- double var = 0 ;
519+ long double p50 = percentile (snapshot, .5 );
520+ long double p95 = percentile (snapshot, .95 );
521+ long double p99 = percentile (snapshot, .99 );
522+ long double var = 0 ;
509523 if (snapshot_size > 1 ) {
510524 for (auto elem : snapshot) {
511- double incr = std::pow (( static_cast < double >( elem) - mean), 2 );
525+ long double incr = std::pow (elem - mean_, static_cast < long double >( 2 ) );
512526 var += incr;
513527 }
514528 var = var / static_cast <double >(snapshot_size);
515529 }
516- double std_dev = std::sqrt (var);
517- return HistogramStats (snapshot_size, min, max, mean , std_dev, p50, p95, p99);
530+ long double std_dev = std::sqrt (var);
531+ return HistogramStats (snapshot_size, min, max, mean_ , std_dev, p50, p95, p99);
518532}
519533
520534MetricType Histogram::type () const { return MetricType::Histogram; }
0 commit comments