Moves SampleStats and EventRateCounter to rtc_base/numerics
Bug: webrtc:9883
Change-Id: I53934c86cad3b7cd60bba6c78e5db66c10e5d56a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/159821
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29965}
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
index 2de8c4f..2b10d1e 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -577,6 +577,8 @@
sources = [
"numerics/event_based_exponential_moving_average.cc",
"numerics/event_based_exponential_moving_average.h",
+ "numerics/event_rate_counter.cc",
+ "numerics/event_rate_counter.h",
"numerics/exp_filter.cc",
"numerics/exp_filter.h",
"numerics/math_utils.h",
@@ -585,6 +587,8 @@
"numerics/moving_median_filter.h",
"numerics/percentile_filter.h",
"numerics/running_statistics.h",
+ "numerics/sample_stats.cc",
+ "numerics/sample_stats.h",
"numerics/samples_stats_counter.cc",
"numerics/samples_stats_counter.h",
"numerics/sequence_number_util.h",
@@ -594,6 +598,8 @@
":rtc_base_approved",
":safe_compare",
"../api:array_view",
+ "../api/units:data_rate",
+ "../api/units:time_delta",
"../api/units:timestamp",
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/types:optional",
diff --git a/rtc_base/numerics/event_rate_counter.cc b/rtc_base/numerics/event_rate_counter.cc
new file mode 100644
index 0000000..d7b7293
--- /dev/null
+++ b/rtc_base/numerics/event_rate_counter.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019 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/numerics/event_rate_counter.h"
+
+#include <algorithm>
+
+namespace webrtc {
+
+void EventRateCounter::AddEvent(Timestamp event_time) {
+ if (first_time_.IsFinite())
+ interval_.AddSample(event_time - last_time_);
+ first_time_ = std::min(first_time_, event_time);
+ last_time_ = std::max(last_time_, event_time);
+ event_count_++;
+}
+
+void EventRateCounter::AddEvents(EventRateCounter other) {
+ first_time_ = std::min(first_time_, other.first_time_);
+ last_time_ = std::max(last_time_, other.last_time_);
+ event_count_ += other.event_count_;
+ interval_.AddSamples(other.interval_);
+}
+
+bool EventRateCounter::IsEmpty() const {
+ return first_time_ == last_time_;
+}
+
+double EventRateCounter::Rate() const {
+ if (event_count_ == 0)
+ return 0;
+ if (event_count_ == 1)
+ return NAN;
+ return (event_count_ - 1) / (last_time_ - first_time_).seconds<double>();
+}
+
+TimeDelta EventRateCounter::TotalDuration() const {
+ if (first_time_.IsInfinite()) {
+ return TimeDelta::Zero();
+ }
+ return last_time_ - first_time_;
+}
+} // namespace webrtc
diff --git a/rtc_base/numerics/event_rate_counter.h b/rtc_base/numerics/event_rate_counter.h
new file mode 100644
index 0000000..ebeac87
--- /dev/null
+++ b/rtc_base/numerics/event_rate_counter.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019 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_NUMERICS_EVENT_RATE_COUNTER_H_
+#define RTC_BASE_NUMERICS_EVENT_RATE_COUNTER_H_
+
+#include "rtc_base/numerics/sample_stats.h"
+
+namespace webrtc {
+
+// Calculates statistics based on events. For example for computing frame rates.
+// Note that it doesn't provide any running statistics or reset funcitonality,
+// so it's mostly useful for end of call statistics.
+class EventRateCounter {
+ public:
+ // Adds an event based on it's |event_time| for correct updates of the
+ // interval statistics, each event must be added past the previous events.
+ void AddEvent(Timestamp event_time);
+ // Adds the events from |other|. Note that the interval stats won't be
+ // recalculated, only merged, so this is not equivalent to if the events would
+ // have been added to the same counter from the start.
+ void AddEvents(EventRateCounter other);
+ bool IsEmpty() const;
+ // Average number of events per second. Defaults to 0 for no events and NAN
+ // for one event.
+ double Rate() const;
+ SampleStats<TimeDelta>& interval() { return interval_; }
+ TimeDelta TotalDuration() const;
+ int Count() const { return event_count_; }
+
+ private:
+ Timestamp first_time_ = Timestamp::PlusInfinity();
+ Timestamp last_time_ = Timestamp::MinusInfinity();
+ int64_t event_count_ = 0;
+ SampleStats<TimeDelta> interval_;
+};
+} // namespace webrtc
+#endif // RTC_BASE_NUMERICS_EVENT_RATE_COUNTER_H_
diff --git a/rtc_base/numerics/sample_stats.cc b/rtc_base/numerics/sample_stats.cc
new file mode 100644
index 0000000..7a6f01e
--- /dev/null
+++ b/rtc_base/numerics/sample_stats.cc
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2019 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/numerics/sample_stats.h"
+
+namespace webrtc {
+
+double SampleStats<double>::Max() {
+ if (IsEmpty())
+ return INFINITY;
+ return GetMax();
+}
+
+double SampleStats<double>::Mean() {
+ if (IsEmpty())
+ return 0;
+ return GetAverage();
+}
+
+double SampleStats<double>::Median() {
+ return Quantile(0.5);
+}
+
+double SampleStats<double>::Quantile(double quantile) {
+ if (IsEmpty())
+ return 0;
+ return GetPercentile(quantile);
+}
+
+double SampleStats<double>::Min() {
+ if (IsEmpty())
+ return -INFINITY;
+ return GetMin();
+}
+
+double SampleStats<double>::Variance() {
+ if (IsEmpty())
+ return 0;
+ return GetVariance();
+}
+
+double SampleStats<double>::StandardDeviation() {
+ return sqrt(Variance());
+}
+
+int SampleStats<double>::Count() {
+ return static_cast<int>(GetSamples().size());
+}
+
+void SampleStats<TimeDelta>::AddSample(TimeDelta delta) {
+ RTC_DCHECK(delta.IsFinite());
+ stats_.AddSample(delta.seconds<double>());
+}
+
+void SampleStats<TimeDelta>::AddSampleMs(double delta_ms) {
+ AddSample(TimeDelta::ms(delta_ms));
+}
+void SampleStats<TimeDelta>::AddSamples(const SampleStats<TimeDelta>& other) {
+ stats_.AddSamples(other.stats_);
+}
+
+bool SampleStats<TimeDelta>::IsEmpty() {
+ return stats_.IsEmpty();
+}
+
+TimeDelta SampleStats<TimeDelta>::Max() {
+ return TimeDelta::seconds(stats_.Max());
+}
+
+TimeDelta SampleStats<TimeDelta>::Mean() {
+ return TimeDelta::seconds(stats_.Mean());
+}
+
+TimeDelta SampleStats<TimeDelta>::Median() {
+ return Quantile(0.5);
+}
+
+TimeDelta SampleStats<TimeDelta>::Quantile(double quantile) {
+ return TimeDelta::seconds(stats_.Quantile(quantile));
+}
+
+TimeDelta SampleStats<TimeDelta>::Min() {
+ return TimeDelta::seconds(stats_.Min());
+}
+
+TimeDelta SampleStats<TimeDelta>::Variance() {
+ return TimeDelta::seconds(stats_.Variance());
+}
+
+TimeDelta SampleStats<TimeDelta>::StandardDeviation() {
+ return TimeDelta::seconds(stats_.StandardDeviation());
+}
+
+int SampleStats<TimeDelta>::Count() {
+ return stats_.Count();
+}
+
+void SampleStats<DataRate>::AddSample(DataRate sample) {
+ stats_.AddSample(sample.bps<double>());
+}
+
+void SampleStats<DataRate>::AddSampleBps(double rate_bps) {
+ stats_.AddSample(rate_bps);
+}
+
+void SampleStats<DataRate>::AddSamples(const SampleStats<DataRate>& other) {
+ stats_.AddSamples(other.stats_);
+}
+
+bool SampleStats<DataRate>::IsEmpty() {
+ return stats_.IsEmpty();
+}
+
+DataRate SampleStats<DataRate>::Max() {
+ return DataRate::bps(stats_.Max());
+}
+
+DataRate SampleStats<DataRate>::Mean() {
+ return DataRate::bps(stats_.Mean());
+}
+
+DataRate SampleStats<DataRate>::Median() {
+ return Quantile(0.5);
+}
+
+DataRate SampleStats<DataRate>::Quantile(double quantile) {
+ return DataRate::bps(stats_.Quantile(quantile));
+}
+
+DataRate SampleStats<DataRate>::Min() {
+ return DataRate::bps(stats_.Min());
+}
+
+DataRate SampleStats<DataRate>::Variance() {
+ return DataRate::bps(stats_.Variance());
+}
+
+DataRate SampleStats<DataRate>::StandardDeviation() {
+ return DataRate::bps(stats_.StandardDeviation());
+}
+
+int SampleStats<DataRate>::Count() {
+ return stats_.Count();
+}
+
+} // namespace webrtc
diff --git a/rtc_base/numerics/sample_stats.h b/rtc_base/numerics/sample_stats.h
new file mode 100644
index 0000000..f634741
--- /dev/null
+++ b/rtc_base/numerics/sample_stats.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2019 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_NUMERICS_SAMPLE_STATS_H_
+#define RTC_BASE_NUMERICS_SAMPLE_STATS_H_
+
+#include "api/units/data_rate.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
+#include "rtc_base/numerics/samples_stats_counter.h"
+
+namespace webrtc {
+template <typename T>
+class SampleStats;
+
+// TODO(srte): Merge this implementation with SamplesStatsCounter.
+template <>
+class SampleStats<double> : public SamplesStatsCounter {
+ public:
+ double Max();
+ double Mean();
+ double Median();
+ double Quantile(double quantile);
+ double Min();
+ double Variance();
+ double StandardDeviation();
+ int Count();
+};
+
+template <>
+class SampleStats<TimeDelta> {
+ public:
+ void AddSample(TimeDelta delta);
+ void AddSampleMs(double delta_ms);
+ void AddSamples(const SampleStats<TimeDelta>& other);
+ bool IsEmpty();
+ TimeDelta Max();
+ TimeDelta Mean();
+ TimeDelta Median();
+ TimeDelta Quantile(double quantile);
+ TimeDelta Min();
+ TimeDelta Variance();
+ TimeDelta StandardDeviation();
+ int Count();
+
+ private:
+ SampleStats<double> stats_;
+};
+
+template <>
+class SampleStats<DataRate> {
+ public:
+ void AddSample(DataRate rate);
+ void AddSampleBps(double rate_bps);
+ void AddSamples(const SampleStats<DataRate>& other);
+ bool IsEmpty();
+ DataRate Max();
+ DataRate Mean();
+ DataRate Median();
+ DataRate Quantile(double quantile);
+ DataRate Min();
+ DataRate Variance();
+ DataRate StandardDeviation();
+ int Count();
+
+ private:
+ SampleStats<double> stats_;
+};
+} // namespace webrtc
+
+#endif // RTC_BASE_NUMERICS_SAMPLE_STATS_H_
diff --git a/test/scenario/performance_stats.cc b/test/scenario/performance_stats.cc
index 5f5b506..e12be8a 100644
--- a/test/scenario/performance_stats.cc
+++ b/test/scenario/performance_stats.cc
@@ -13,178 +13,6 @@
namespace webrtc {
namespace test {
-void EventRateCounter::AddEvent(Timestamp event_time) {
- if (first_time_.IsFinite())
- interval_.AddSample(event_time - last_time_);
- first_time_ = std::min(first_time_, event_time);
- last_time_ = std::max(last_time_, event_time);
- event_count_++;
-}
-
-void EventRateCounter::AddEvents(EventRateCounter other) {
- first_time_ = std::min(first_time_, other.first_time_);
- last_time_ = std::max(last_time_, other.last_time_);
- event_count_ += other.event_count_;
- interval_.AddSamples(other.interval_);
-}
-
-bool EventRateCounter::IsEmpty() const {
- return first_time_ == last_time_;
-}
-
-double EventRateCounter::Rate() const {
- if (event_count_ == 0)
- return 0;
- if (event_count_ == 1)
- return NAN;
- return (event_count_ - 1) / (last_time_ - first_time_).seconds<double>();
-}
-
-TimeDelta EventRateCounter::TotalDuration() const {
- if (first_time_.IsInfinite()) {
- return TimeDelta::Zero();
- }
- return last_time_ - first_time_;
-}
-
-double SampleStats<double>::Max() {
- if (IsEmpty())
- return INFINITY;
- return GetMax();
-}
-
-double SampleStats<double>::Mean() {
- if (IsEmpty())
- return 0;
- return GetAverage();
-}
-
-double SampleStats<double>::Median() {
- return Quantile(0.5);
-}
-
-double SampleStats<double>::Quantile(double quantile) {
- if (IsEmpty())
- return 0;
- return GetPercentile(quantile);
-}
-
-double SampleStats<double>::Min() {
- if (IsEmpty())
- return -INFINITY;
- return GetMin();
-}
-
-double SampleStats<double>::Variance() {
- if (IsEmpty())
- return 0;
- return GetVariance();
-}
-
-double SampleStats<double>::StandardDeviation() {
- return sqrt(Variance());
-}
-
-int SampleStats<double>::Count() {
- return static_cast<int>(GetSamples().size());
-}
-
-void SampleStats<TimeDelta>::AddSample(TimeDelta delta) {
- RTC_DCHECK(delta.IsFinite());
- stats_.AddSample(delta.seconds<double>());
-}
-
-void SampleStats<TimeDelta>::AddSampleMs(double delta_ms) {
- AddSample(TimeDelta::ms(delta_ms));
-}
-void SampleStats<TimeDelta>::AddSamples(const SampleStats<TimeDelta>& other) {
- stats_.AddSamples(other.stats_);
-}
-
-bool SampleStats<TimeDelta>::IsEmpty() {
- return stats_.IsEmpty();
-}
-
-TimeDelta SampleStats<TimeDelta>::Max() {
- return TimeDelta::seconds(stats_.Max());
-}
-
-TimeDelta SampleStats<TimeDelta>::Mean() {
- return TimeDelta::seconds(stats_.Mean());
-}
-
-TimeDelta SampleStats<TimeDelta>::Median() {
- return Quantile(0.5);
-}
-
-TimeDelta SampleStats<TimeDelta>::Quantile(double quantile) {
- return TimeDelta::seconds(stats_.Quantile(quantile));
-}
-
-TimeDelta SampleStats<TimeDelta>::Min() {
- return TimeDelta::seconds(stats_.Min());
-}
-
-TimeDelta SampleStats<TimeDelta>::Variance() {
- return TimeDelta::seconds(stats_.Variance());
-}
-
-TimeDelta SampleStats<TimeDelta>::StandardDeviation() {
- return TimeDelta::seconds(stats_.StandardDeviation());
-}
-
-int SampleStats<TimeDelta>::Count() {
- return stats_.Count();
-}
-
-void SampleStats<DataRate>::AddSample(DataRate sample) {
- stats_.AddSample(sample.bps<double>());
-}
-
-void SampleStats<DataRate>::AddSampleBps(double rate_bps) {
- stats_.AddSample(rate_bps);
-}
-
-void SampleStats<DataRate>::AddSamples(const SampleStats<DataRate>& other) {
- stats_.AddSamples(other.stats_);
-}
-
-bool SampleStats<DataRate>::IsEmpty() {
- return stats_.IsEmpty();
-}
-
-DataRate SampleStats<DataRate>::Max() {
- return DataRate::bps(stats_.Max());
-}
-
-DataRate SampleStats<DataRate>::Mean() {
- return DataRate::bps(stats_.Mean());
-}
-
-DataRate SampleStats<DataRate>::Median() {
- return Quantile(0.5);
-}
-
-DataRate SampleStats<DataRate>::Quantile(double quantile) {
- return DataRate::bps(stats_.Quantile(quantile));
-}
-
-DataRate SampleStats<DataRate>::Min() {
- return DataRate::bps(stats_.Min());
-}
-
-DataRate SampleStats<DataRate>::Variance() {
- return DataRate::bps(stats_.Variance());
-}
-
-DataRate SampleStats<DataRate>::StandardDeviation() {
- return DataRate::bps(stats_.StandardDeviation());
-}
-
-int SampleStats<DataRate>::Count() {
- return stats_.Count();
-}
-
void VideoFramesStats::AddFrameInfo(const VideoFrameBuffer& frame,
Timestamp at_time) {
++count;
diff --git a/test/scenario/performance_stats.h b/test/scenario/performance_stats.h
index 310ee8d..6974ab6 100644
--- a/test/scenario/performance_stats.h
+++ b/test/scenario/performance_stats.h
@@ -14,7 +14,8 @@
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "api/video/video_frame_buffer.h"
-#include "rtc_base/numerics/samples_stats_counter.h"
+#include "rtc_base/numerics/event_rate_counter.h"
+#include "rtc_base/numerics/sample_stats.h"
namespace webrtc {
namespace test {
@@ -36,78 +37,6 @@
int repeated = 0;
};
-template <typename T>
-class SampleStats;
-
-template <>
-class SampleStats<double> : public SamplesStatsCounter {
- public:
- double Max();
- double Mean();
- double Median();
- double Quantile(double quantile);
- double Min();
- double Variance();
- double StandardDeviation();
- int Count();
-};
-
-template <>
-class SampleStats<TimeDelta> {
- public:
- void AddSample(TimeDelta delta);
- void AddSampleMs(double delta_ms);
- void AddSamples(const SampleStats<TimeDelta>& other);
- bool IsEmpty();
- TimeDelta Max();
- TimeDelta Mean();
- TimeDelta Median();
- TimeDelta Quantile(double quantile);
- TimeDelta Min();
- TimeDelta Variance();
- TimeDelta StandardDeviation();
- int Count();
-
- private:
- SampleStats<double> stats_;
-};
-
-template <>
-class SampleStats<DataRate> {
- public:
- void AddSample(DataRate rate);
- void AddSampleBps(double rate_bps);
- void AddSamples(const SampleStats<DataRate>& other);
- bool IsEmpty();
- DataRate Max();
- DataRate Mean();
- DataRate Median();
- DataRate Quantile(double quantile);
- DataRate Min();
- DataRate Variance();
- DataRate StandardDeviation();
- int Count();
-
- private:
- SampleStats<double> stats_;
-};
-
-class EventRateCounter {
- public:
- void AddEvent(Timestamp event_time);
- void AddEvents(EventRateCounter other);
- bool IsEmpty() const;
- double Rate() const;
- SampleStats<TimeDelta>& interval() { return interval_; }
- TimeDelta TotalDuration() const;
- int Count() const { return event_count_; }
-
- private:
- Timestamp first_time_ = Timestamp::PlusInfinity();
- Timestamp last_time_ = Timestamp::MinusInfinity();
- int64_t event_count_ = 0;
- SampleStats<TimeDelta> interval_;
-};
struct VideoFramesStats {
int count = 0;