samples_stats_counter.cc (3400B)
1 /* 2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "api/numerics/samples_stats_counter.h" 12 13 #include <algorithm> 14 #include <cmath> 15 #include <cstddef> 16 17 #include "absl/algorithm/container.h" 18 #include "api/units/timestamp.h" 19 #include "rtc_base/checks.h" 20 #include "rtc_base/time_utils.h" 21 22 namespace webrtc { 23 24 SamplesStatsCounter::SamplesStatsCounter() = default; 25 SamplesStatsCounter::SamplesStatsCounter(size_t expected_samples_count) { 26 samples_.reserve(expected_samples_count); 27 } 28 29 SamplesStatsCounter::~SamplesStatsCounter() = default; 30 SamplesStatsCounter::SamplesStatsCounter(const SamplesStatsCounter&) = default; 31 SamplesStatsCounter& SamplesStatsCounter::operator=( 32 const SamplesStatsCounter&) = default; 33 SamplesStatsCounter::SamplesStatsCounter(SamplesStatsCounter&&) = default; 34 SamplesStatsCounter& SamplesStatsCounter::operator=(SamplesStatsCounter&&) = 35 default; 36 37 void SamplesStatsCounter::AddSample(double value) { 38 AddSample( 39 StatsSample{.value = value, .time = Timestamp::Micros(TimeMicros())}); 40 } 41 42 void SamplesStatsCounter::AddSample(StatsSample sample) { 43 stats_.AddSample(sample.value); 44 samples_.push_back(sample); 45 sorted_ = false; 46 } 47 48 void SamplesStatsCounter::AddSamples(const SamplesStatsCounter& other) { 49 stats_.MergeStatistics(other.stats_); 50 samples_.insert(samples_.end(), other.samples_.begin(), other.samples_.end()); 51 sorted_ = false; 52 } 53 54 double SamplesStatsCounter::GetPercentile(double percentile) { 55 RTC_DCHECK(!IsEmpty()); 56 RTC_CHECK_GE(percentile, 0); 57 RTC_CHECK_LE(percentile, 1); 58 if (!sorted_) { 59 absl::c_sort(samples_, [](const StatsSample& a, const StatsSample& b) { 60 return a.value < b.value; 61 }); 62 sorted_ = true; 63 } 64 const double raw_rank = percentile * (samples_.size() - 1); 65 double int_part; 66 double fract_part = std::modf(raw_rank, &int_part); 67 size_t rank = static_cast<size_t>(int_part); 68 if (fract_part >= 1.0) { 69 // It can happen due to floating point calculation error. 70 rank++; 71 fract_part -= 1.0; 72 } 73 74 RTC_DCHECK_GE(rank, 0); 75 RTC_DCHECK_LT(rank, samples_.size()); 76 RTC_DCHECK_GE(fract_part, 0); 77 RTC_DCHECK_LT(fract_part, 1); 78 RTC_DCHECK(rank + fract_part == raw_rank); 79 80 const double low = samples_[rank].value; 81 const double high = samples_[std::min(rank + 1, samples_.size() - 1)].value; 82 return low + fract_part * (high - low); 83 } 84 85 SamplesStatsCounter operator*(const SamplesStatsCounter& counter, 86 double value) { 87 SamplesStatsCounter out; 88 for (const auto& sample : counter.GetTimedSamples()) { 89 out.AddSample(SamplesStatsCounter::StatsSample{ 90 .value = sample.value * value, .time = sample.time}); 91 } 92 return out; 93 } 94 95 SamplesStatsCounter operator/(const SamplesStatsCounter& counter, 96 double value) { 97 SamplesStatsCounter out; 98 for (const auto& sample : counter.GetTimedSamples()) { 99 out.AddSample(SamplesStatsCounter::StatsSample{ 100 .value = sample.value / value, .time = sample.time}); 101 } 102 return out; 103 } 104 105 } // namespace webrtc