Move HistogramPercentileCounter to rtc_base from RecieveStatisticProxy.

This should be a separate utility class, rather than internal thing in
ReceiveStatisticsProxy.

Bug: webrtc:8347
Change-Id: I9c8238e625999dba5776d6038c819732d07e9656
Reviewed-on: https://webrtc-review.googlesource.com/7609
Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20267}
This commit is contained in:
Ilya Nikolaevskiy
2017-10-12 12:38:01 +02:00
committed by Commit Bot
parent 86f25d3bcd
commit ed23be91b8
7 changed files with 170 additions and 107 deletions

View File

@ -137,6 +137,8 @@ rtc_source_set("rtc_base_approved_generic") {
"flags.h",
"format_macros.h",
"function_view.h",
"histogram_percentile_counter.cc",
"histogram_percentile_counter.h",
"ignore_wundef.h",
"location.cc",
"location.h",
@ -895,6 +897,7 @@ if (rtc_include_tests) {
"event_unittest.cc",
"file_unittest.cc",
"function_view_unittest.cc",
"histogram_percentile_counter_unittest.cc",
"logging_unittest.cc",
"md5digest_unittest.cc",
"mod_ops_unittest.cc",

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "rtc_base/histogram_percentile_counter.h"
#include <algorithm>
#include <cmath>
#include "rtc_base/checks.h"
namespace rtc {
HistogramPercentileCounter::HistogramPercentileCounter(
uint32_t long_tail_boundary)
: histogram_low_(size_t{long_tail_boundary}),
long_tail_boundary_(long_tail_boundary),
total_elements_(0),
total_elements_low_(0) {}
HistogramPercentileCounter::~HistogramPercentileCounter() = default;
void HistogramPercentileCounter::Add(const HistogramPercentileCounter& other) {
for (uint32_t value = 0; value < other.long_tail_boundary_; ++value) {
Add(value, other.histogram_low_[value]);
}
for (const auto& it : histogram_high_) {
Add(it.first, it.second);
}
}
void HistogramPercentileCounter::Add(uint32_t value, size_t count) {
if (value < long_tail_boundary_) {
histogram_low_[value] += count;
total_elements_low_ += count;
} else {
histogram_high_[value] += count;
}
total_elements_ += count;
}
void HistogramPercentileCounter::Add(uint32_t value) {
Add(value, 1);
}
rtc::Optional<uint32_t> HistogramPercentileCounter::GetPercentile(
float fraction) {
RTC_CHECK_LE(fraction, 1.0);
RTC_CHECK_GE(fraction, 0.0);
if (total_elements_ == 0)
return rtc::Optional<uint32_t>();
size_t elements_to_skip = static_cast<size_t>(
std::max(0.0f, std::ceil(total_elements_ * fraction) - 1));
if (elements_to_skip >= total_elements_)
elements_to_skip = total_elements_ - 1;
if (elements_to_skip < total_elements_low_) {
for (uint32_t value = 0; value < long_tail_boundary_; ++value) {
if (elements_to_skip < histogram_low_[value])
return rtc::Optional<uint32_t>(value);
elements_to_skip -= histogram_low_[value];
}
} else {
elements_to_skip -= total_elements_low_;
for (const auto& it : histogram_high_) {
if (elements_to_skip < it.second)
return rtc::Optional<uint32_t>(it.first);
elements_to_skip -= it.second;
}
}
RTC_NOTREACHED();
return rtc::Optional<uint32_t>();
}
} // namespace rtc

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef RTC_BASE_HISTOGRAM_PERCENTILE_COUNTER_H_
#define RTC_BASE_HISTOGRAM_PERCENTILE_COUNTER_H_
#include <stdint.h>
#include <map>
#include <vector>
#include "api/optional.h"
namespace rtc {
// Calculates percentiles on the stream of data. Use |Add| methods to add new
// values. Use |GetPercentile| to get percentile of the currently added values.
class HistogramPercentileCounter {
public:
// Values below |long_tail_boundary| are stored as the histogram in an array.
// Values above - in a map.
explicit HistogramPercentileCounter(uint32_t long_tail_boundary);
~HistogramPercentileCounter();
void Add(uint32_t value);
void Add(uint32_t value, size_t count);
void Add(const HistogramPercentileCounter& other);
// Argument should be from 0 to 1.
rtc::Optional<uint32_t> GetPercentile(float fraction);
private:
std::vector<size_t> histogram_low_;
std::map<uint32_t, size_t> histogram_high_;
const uint32_t long_tail_boundary_;
size_t total_elements_;
size_t total_elements_low_;
};
} // namespace rtc
#endif // RTC_BASE_HISTOGRAM_PERCENTILE_COUNTER_H_

View File

@ -0,0 +1,43 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "rtc_base/histogram_percentile_counter.h"
#include <utility>
#include <vector>
#include "test/gtest.h"
TEST(HistogramPercentileCounterTest, ReturnsCorrectPercentiles) {
rtc::HistogramPercentileCounter counter(10);
const std::vector<int> kTestValues = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
EXPECT_FALSE(counter.GetPercentile(0.5f));
// Pairs of {fraction, percentile value} computed by hand
// for |kTestValues|.
const std::vector<std::pair<float, uint32_t>> kTestPercentiles = {
{0.0f, 1}, {0.01f, 1}, {0.5f, 10}, {0.9f, 18},
{0.95f, 19}, {0.99f, 20}, {1.0f, 20}};
for (int value : kTestValues) {
counter.Add(value);
}
for (const auto& test_percentile : kTestPercentiles) {
EXPECT_EQ(test_percentile.second,
counter.GetPercentile(test_percentile.first).value_or(0));
}
}
TEST(HistogramPercentileCounterTest, HandlesEmptySequence) {
rtc::HistogramPercentileCounter counter(10);
EXPECT_FALSE(counter.GetPercentile(0.5f));
counter.Add(1u);
EXPECT_TRUE(counter.GetPercentile(0.5f));
}