mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-14 14:20:45 +01:00
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:
parent
86f25d3bcd
commit
ed23be91b8
7 changed files with 170 additions and 107 deletions
|
@ -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",
|
||||
|
|
79
rtc_base/histogram_percentile_counter.cc
Normal file
79
rtc_base/histogram_percentile_counter.cc
Normal 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
|
43
rtc_base/histogram_percentile_counter.h
Normal file
43
rtc_base/histogram_percentile_counter.h
Normal 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_
|
43
rtc_base/histogram_percentile_counter_unittest.cc
Normal file
43
rtc_base/histogram_percentile_counter_unittest.cc
Normal 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));
|
||||
}
|
|
@ -821,69 +821,4 @@ void ReceiveStatisticsProxy::ContentSpecificStats::Add(
|
|||
frame_counts.delta_frames += other.frame_counts.delta_frames;
|
||||
interframe_delay_percentiles.Add(other.interframe_delay_percentiles);
|
||||
}
|
||||
|
||||
ReceiveStatisticsProxy::HistogramPercentileCounter::HistogramPercentileCounter(
|
||||
size_t long_tail_boundary)
|
||||
: histogram_low_(long_tail_boundary),
|
||||
long_tail_boundary_(long_tail_boundary),
|
||||
total_elements_(0),
|
||||
total_elements_low_(0) {}
|
||||
|
||||
void ReceiveStatisticsProxy::HistogramPercentileCounter::Add(
|
||||
const HistogramPercentileCounter& other) {
|
||||
uint32_t value;
|
||||
for (value = 0; value < other.long_tail_boundary_; ++value) {
|
||||
Add(value, other.histogram_low_[value]);
|
||||
}
|
||||
for (auto it = other.histogram_high_.begin();
|
||||
it != other.histogram_high_.end(); ++it) {
|
||||
Add(it->first, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
void ReceiveStatisticsProxy::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 ReceiveStatisticsProxy::HistogramPercentileCounter::Add(uint32_t value) {
|
||||
Add(value, 1);
|
||||
}
|
||||
|
||||
rtc::Optional<uint32_t>
|
||||
ReceiveStatisticsProxy::HistogramPercentileCounter::GetPercentile(
|
||||
float fraction) {
|
||||
RTC_CHECK_LE(fraction, 1);
|
||||
RTC_CHECK_GE(fraction, 0);
|
||||
if (total_elements_ == 0)
|
||||
return rtc::Optional<uint32_t>();
|
||||
int elements_to_skip =
|
||||
static_cast<int>(std::ceil(total_elements_ * fraction)) - 1;
|
||||
if (elements_to_skip < 0)
|
||||
elements_to_skip = 0;
|
||||
if (elements_to_skip >= static_cast<int>(total_elements_))
|
||||
elements_to_skip = total_elements_ - 1;
|
||||
if (elements_to_skip < static_cast<int>(total_elements_low_)) {
|
||||
for (uint32_t value = 0; value < long_tail_boundary_; ++value) {
|
||||
elements_to_skip -= histogram_low_[value];
|
||||
if (elements_to_skip < 0)
|
||||
return rtc::Optional<uint32_t>(value);
|
||||
}
|
||||
} else {
|
||||
elements_to_skip -= total_elements_low_;
|
||||
for (auto it = histogram_high_.begin(); it != histogram_high_.end(); ++it) {
|
||||
elements_to_skip -= it->second;
|
||||
if (elements_to_skip < 0)
|
||||
return rtc::Optional<uint32_t>(it->first);
|
||||
}
|
||||
}
|
||||
RTC_NOTREACHED();
|
||||
return rtc::Optional<uint32_t>();
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "common_video/include/frame_callback.h"
|
||||
#include "modules/video_coding/include/video_coding_defines.h"
|
||||
#include "rtc_base/criticalsection.h"
|
||||
#include "rtc_base/histogram_percentile_counter.h"
|
||||
#include "rtc_base/moving_max_counter.h"
|
||||
#include "rtc_base/rate_statistics.h"
|
||||
#include "rtc_base/ratetracker.h"
|
||||
|
@ -95,25 +96,6 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback,
|
|||
// Implements CallStatsObserver.
|
||||
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
|
||||
|
||||
class HistogramPercentileCounter {
|
||||
public:
|
||||
// Values below |long_tail_boundary| are stored in the array.
|
||||
// Values above - in the map.
|
||||
explicit HistogramPercentileCounter(size_t long_tail_boundary);
|
||||
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 size_t long_tail_boundary_;
|
||||
size_t total_elements_;
|
||||
size_t total_elements_low_;
|
||||
};
|
||||
|
||||
private:
|
||||
struct SampleCounter {
|
||||
SampleCounter() : sum(0), num_samples(0) {}
|
||||
|
@ -146,7 +128,7 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback,
|
|||
SampleCounter received_height;
|
||||
SampleCounter qp_counter;
|
||||
FrameCounts frame_counts;
|
||||
HistogramPercentileCounter interframe_delay_percentiles;
|
||||
rtc::HistogramPercentileCounter interframe_delay_percentiles;
|
||||
};
|
||||
|
||||
void UpdateHistograms() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||
|
|
|
@ -999,26 +999,4 @@ TEST_P(ReceiveStatisticsProxyTest, StatsAreSlicedOnSimulcastAndExperiment) {
|
|||
"WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ReceiveStatisticsProxyTest, PercentileCounterReturnsCorrectPercentiles) {
|
||||
ReceiveStatisticsProxy::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}};
|
||||
size_t i;
|
||||
for (i = 0; i < kTestValues.size(); ++i) {
|
||||
counter.Add(kTestValues[i]);
|
||||
}
|
||||
for (i = 0; i < kTestPercentiles.size(); ++i) {
|
||||
EXPECT_EQ(kTestPercentiles[i].second,
|
||||
counter.GetPercentile(kTestPercentiles[i].first).value_or(0));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
Loading…
Reference in a new issue