Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Side by Side Diff: webrtc/video/stats_counter.cc

Issue 2307913002: Update AvgCounter to have the ability to include last period metric for subsequent intervals withou… (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/video/stats_counter.h ('k') | webrtc/video/stats_counter_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/video/stats_counter.h" 11 #include "webrtc/video/stats_counter.h"
12 12
13 #include <algorithm> 13 #include <algorithm>
14 14
15 #include "webrtc/base/checks.h"
15 #include "webrtc/system_wrappers/include/clock.h" 16 #include "webrtc/system_wrappers/include/clock.h"
16 17
17 namespace webrtc { 18 namespace webrtc {
18 19
19 namespace { 20 namespace {
20 // Periodic time interval for processing samples. 21 // Periodic time interval for processing samples.
21 const int64_t kProcessIntervalMs = 2000; 22 const int64_t kProcessIntervalMs = 2000;
22 } // namespace 23 } // namespace
23 24
24 // Class holding periodically computed metrics. 25 // Class holding periodically computed metrics.
25 class AggregatedCounter { 26 class AggregatedCounter {
26 public: 27 public:
27 AggregatedCounter() : sum_(0) {} 28 AggregatedCounter() : last_sample_(0), sum_samples_(0) {}
28 ~AggregatedCounter() {} 29 ~AggregatedCounter() {}
29 30
30 void Add(int sample) { 31 void Add(int sample) {
31 sum_ += sample; 32 last_sample_ = sample;
33 sum_samples_ += sample;
32 ++stats_.num_samples; 34 ++stats_.num_samples;
33 if (stats_.num_samples == 1) { 35 if (stats_.num_samples == 1) {
34 stats_.min = sample; 36 stats_.min = sample;
35 stats_.max = sample; 37 stats_.max = sample;
36 } 38 }
37 stats_.min = std::min(sample, stats_.min); 39 stats_.min = std::min(sample, stats_.min);
38 stats_.max = std::max(sample, stats_.max); 40 stats_.max = std::max(sample, stats_.max);
39 } 41 }
40 42
41 AggregatedStats ComputeStats() { 43 AggregatedStats ComputeStats() {
42 Compute(); 44 Compute();
43 return stats_; 45 return stats_;
44 } 46 }
45 47
48 bool HasSamples() const { return stats_.num_samples > 0; }
stefan-webrtc 2016/09/08 07:28:14 Maybe call this Empty() instead to align with inte
åsapersson 2016/09/08 13:15:02 Done.
49
50 int last_sample() const { return last_sample_; }
51
46 private: 52 private:
47 void Compute() { 53 void Compute() {
48 if (stats_.num_samples == 0) 54 if (stats_.num_samples == 0)
49 return; 55 return;
50 56
51 stats_.average = (sum_ + stats_.num_samples / 2) / stats_.num_samples; 57 stats_.average =
58 (sum_samples_ + stats_.num_samples / 2) / stats_.num_samples;
52 } 59 }
53 int64_t sum_; 60 int last_sample_;
61 int64_t sum_samples_;
54 AggregatedStats stats_; 62 AggregatedStats stats_;
55 }; 63 };
56 64
57 // StatsCounter class. 65 // StatsCounter class.
58 StatsCounter::StatsCounter(Clock* clock, 66 StatsCounter::StatsCounter(Clock* clock,
59 bool include_empty_intervals, 67 bool include_empty_intervals,
60 StatsCounterObserver* observer) 68 StatsCounterObserver* observer)
61 : max_(0), 69 : max_(0),
62 sum_(0), 70 sum_(0),
63 num_samples_(0), 71 num_samples_(0),
64 last_sum_(0), 72 last_sum_(0),
73 aggregated_counter_(new AggregatedCounter()),
65 clock_(clock), 74 clock_(clock),
66 include_empty_intervals_(include_empty_intervals), 75 include_empty_intervals_(include_empty_intervals),
67 observer_(observer), 76 observer_(observer),
68 aggregated_counter_(new AggregatedCounter()), 77 last_process_time_ms_(-1),
69 last_process_time_ms_(-1) {} 78 paused_(false) {}
70 79
71 StatsCounter::~StatsCounter() {} 80 StatsCounter::~StatsCounter() {}
72 81
73 AggregatedStats StatsCounter::GetStats() { 82 AggregatedStats StatsCounter::GetStats() {
74 return aggregated_counter_->ComputeStats(); 83 return aggregated_counter_->ComputeStats();
75 } 84 }
76 85
77 bool StatsCounter::TimeToProcess() { 86 AggregatedStats StatsCounter::ProcessAndGetStats() {
87 if (last_process_time_ms_ != -1)
88 TryProcess(); // At least one sample is added.
89 return aggregated_counter_->ComputeStats();
90 }
91
92 void StatsCounter::ProcessAndPause() {
93 if (last_process_time_ms_ != -1)
94 TryProcess(); // At least one sample is added.
95 paused_ = true;
96 }
97
98 bool StatsCounter::TimeToProcess(int* elapsed_intervals) {
78 int64_t now = clock_->TimeInMilliseconds(); 99 int64_t now = clock_->TimeInMilliseconds();
79 if (last_process_time_ms_ == -1) 100 if (last_process_time_ms_ == -1)
80 last_process_time_ms_ = now; 101 last_process_time_ms_ = now;
81 102
82 int64_t diff_ms = now - last_process_time_ms_; 103 int64_t diff_ms = now - last_process_time_ms_;
83 if (diff_ms < kProcessIntervalMs) 104 if (diff_ms < kProcessIntervalMs)
84 return false; 105 return false;
85 106
86 // Advance number of complete kProcessIntervalMs that have passed. 107 // Advance number of complete kProcessIntervalMs that have passed.
87 int64_t num_intervals = diff_ms / kProcessIntervalMs; 108 int64_t num_intervals = diff_ms / kProcessIntervalMs;
88 last_process_time_ms_ += num_intervals * kProcessIntervalMs; 109 last_process_time_ms_ += num_intervals * kProcessIntervalMs;
89 110
90 // Add zero for intervals without samples. 111 *elapsed_intervals = num_intervals;
91 if (include_empty_intervals_) {
92 for (int64_t i = 0; i < num_intervals - 1; ++i) {
93 aggregated_counter_->Add(0);
94 if (observer_)
95 observer_->OnMetricUpdated(0);
96 }
97 }
98 return true; 112 return true;
99 } 113 }
100 114
101 void StatsCounter::Set(int sample) { 115 void StatsCounter::Set(int sample) {
102 TryProcess(); 116 TryProcess();
103 ++num_samples_; 117 ++num_samples_;
104 sum_ = sample; 118 sum_ = sample;
119 paused_ = false;
105 } 120 }
106 121
107 void StatsCounter::Add(int sample) { 122 void StatsCounter::Add(int sample) {
108 TryProcess(); 123 TryProcess();
109 ++num_samples_; 124 ++num_samples_;
110 sum_ += sample; 125 sum_ += sample;
111 126
112 if (num_samples_ == 1) 127 if (num_samples_ == 1)
113 max_ = sample; 128 max_ = sample;
114 max_ = std::max(sample, max_); 129 max_ = std::max(sample, max_);
130 paused_ = false;
131 }
132
133 // Reports periodically computed metric.
134 void StatsCounter::ReportMetricToAggregatedCounter(
135 int value,
136 int num_values_to_add) const {
137 for (int i = 0; i < num_values_to_add; ++i) {
138 aggregated_counter_->Add(value);
139 if (observer_)
140 observer_->OnMetricUpdated(value);
141 }
115 } 142 }
116 143
117 void StatsCounter::TryProcess() { 144 void StatsCounter::TryProcess() {
118 if (!TimeToProcess()) 145 int elapsed_intervals;
146 if (!TimeToProcess(&elapsed_intervals))
119 return; 147 return;
120 148
149 // Get and report periodically computed metric.
121 int metric; 150 int metric;
122 if (GetMetric(&metric)) { 151 if (GetMetric(&metric))
123 aggregated_counter_->Add(metric); 152 ReportMetricToAggregatedCounter(metric, 1);
124 if (observer_) 153
125 observer_->OnMetricUpdated(metric); 154 // Report value for elapsed intervals without samples.
155 if (IncludeEmptyIntervals()) {
156 int empty_intervals =
157 (num_samples_ == 0) ? elapsed_intervals : (elapsed_intervals - 1);
stefan-webrtc 2016/09/08 07:28:14 I don't follow this, maybe add a comment on why we
åsapersson 2016/09/08 13:15:02 Done.
158 ReportMetricToAggregatedCounter(GetValueForEmptyInterval(),
159 empty_intervals);
126 } 160 }
127 last_sum_ = sum_; 161
162 // Reset samples for elapsed interval.
163 if (num_samples_ > 0)
164 last_sum_ = sum_;
128 sum_ = 0; 165 sum_ = 0;
129 max_ = 0; 166 max_ = 0;
130 num_samples_ = 0; 167 num_samples_ = 0;
131 } 168 }
132 169
170 bool StatsCounter::IncludeEmptyIntervals() const {
171 return include_empty_intervals_ && !paused_ &&
172 aggregated_counter_->HasSamples();
173 }
174
133 // StatsCounter sub-classes. 175 // StatsCounter sub-classes.
134 AvgCounter::AvgCounter(Clock* clock, StatsCounterObserver* observer) 176 AvgCounter::AvgCounter(Clock* clock,
135 : StatsCounter(clock, 177 StatsCounterObserver* observer,
136 false, // |include_empty_intervals| 178 bool include_empty_intervals)
137 observer) {} 179 : StatsCounter(clock, include_empty_intervals, observer) {}
138 180
139 void AvgCounter::Add(int sample) { 181 void AvgCounter::Add(int sample) {
140 StatsCounter::Add(sample); 182 StatsCounter::Add(sample);
141 } 183 }
142 184
143 bool AvgCounter::GetMetric(int* metric) const { 185 bool AvgCounter::GetMetric(int* metric) const {
144 if (num_samples_ == 0) 186 if (num_samples_ == 0)
145 return false; 187 return false;
146 *metric = (sum_ + num_samples_ / 2) / num_samples_; 188 *metric = (sum_ + num_samples_ / 2) / num_samples_;
147 return true; 189 return true;
148 } 190 }
149 191
192 int AvgCounter::GetValueForEmptyInterval() const {
193 return aggregated_counter_->last_sample();
194 }
195
150 MaxCounter::MaxCounter(Clock* clock, StatsCounterObserver* observer) 196 MaxCounter::MaxCounter(Clock* clock, StatsCounterObserver* observer)
151 : StatsCounter(clock, 197 : StatsCounter(clock,
152 false, // |include_empty_intervals| 198 false, // |include_empty_intervals|
153 observer) {} 199 observer) {}
154 200
155 void MaxCounter::Add(int sample) { 201 void MaxCounter::Add(int sample) {
156 StatsCounter::Add(sample); 202 StatsCounter::Add(sample);
157 } 203 }
158 204
159 bool MaxCounter::GetMetric(int* metric) const { 205 bool MaxCounter::GetMetric(int* metric) const {
160 if (num_samples_ == 0) 206 if (num_samples_ == 0)
161 return false; 207 return false;
162 *metric = max_; 208 *metric = max_;
163 return true; 209 return true;
164 } 210 }
165 211
212 int MaxCounter::GetValueForEmptyInterval() const {
213 RTC_NOTREACHED();
214 return 0;
215 }
216
166 PercentCounter::PercentCounter(Clock* clock, StatsCounterObserver* observer) 217 PercentCounter::PercentCounter(Clock* clock, StatsCounterObserver* observer)
167 : StatsCounter(clock, 218 : StatsCounter(clock,
168 false, // |include_empty_intervals| 219 false, // |include_empty_intervals|
169 observer) {} 220 observer) {}
170 221
171 void PercentCounter::Add(bool sample) { 222 void PercentCounter::Add(bool sample) {
172 StatsCounter::Add(sample ? 1 : 0); 223 StatsCounter::Add(sample ? 1 : 0);
173 } 224 }
174 225
175 bool PercentCounter::GetMetric(int* metric) const { 226 bool PercentCounter::GetMetric(int* metric) const {
176 if (num_samples_ == 0) 227 if (num_samples_ == 0)
177 return false; 228 return false;
178 *metric = (sum_ * 100 + num_samples_ / 2) / num_samples_; 229 *metric = (sum_ * 100 + num_samples_ / 2) / num_samples_;
179 return true; 230 return true;
180 } 231 }
181 232
233 int PercentCounter::GetValueForEmptyInterval() const {
234 RTC_NOTREACHED();
235 return 0;
236 }
237
182 PermilleCounter::PermilleCounter(Clock* clock, StatsCounterObserver* observer) 238 PermilleCounter::PermilleCounter(Clock* clock, StatsCounterObserver* observer)
183 : StatsCounter(clock, 239 : StatsCounter(clock,
184 false, // |include_empty_intervals| 240 false, // |include_empty_intervals|
185 observer) {} 241 observer) {}
186 242
187 void PermilleCounter::Add(bool sample) { 243 void PermilleCounter::Add(bool sample) {
188 StatsCounter::Add(sample ? 1 : 0); 244 StatsCounter::Add(sample ? 1 : 0);
189 } 245 }
190 246
191 bool PermilleCounter::GetMetric(int* metric) const { 247 bool PermilleCounter::GetMetric(int* metric) const {
192 if (num_samples_ == 0) 248 if (num_samples_ == 0)
193 return false; 249 return false;
194 *metric = (sum_ * 1000 + num_samples_ / 2) / num_samples_; 250 *metric = (sum_ * 1000 + num_samples_ / 2) / num_samples_;
195 return true; 251 return true;
196 } 252 }
197 253
254 int PermilleCounter::GetValueForEmptyInterval() const {
255 RTC_NOTREACHED();
256 return 0;
257 }
258
198 RateCounter::RateCounter(Clock* clock, 259 RateCounter::RateCounter(Clock* clock,
199 StatsCounterObserver* observer, 260 StatsCounterObserver* observer,
200 bool include_empty_intervals) 261 bool include_empty_intervals)
201 : StatsCounter(clock, include_empty_intervals, observer) {} 262 : StatsCounter(clock, include_empty_intervals, observer) {}
202 263
203 void RateCounter::Add(int sample) { 264 void RateCounter::Add(int sample) {
204 StatsCounter::Add(sample); 265 StatsCounter::Add(sample);
205 } 266 }
206 267
207 bool RateCounter::GetMetric(int* metric) const { 268 bool RateCounter::GetMetric(int* metric) const {
208 if (num_samples_ == 0) 269 if (num_samples_ == 0)
209 return false; 270 return false;
210 *metric = (sum_ * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; 271 *metric = (sum_ * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs;
211 return true; 272 return true;
212 } 273 }
213 274
275 int RateCounter::GetValueForEmptyInterval() const {
276 return 0;
277 }
278
214 RateAccCounter::RateAccCounter(Clock* clock, 279 RateAccCounter::RateAccCounter(Clock* clock,
215 StatsCounterObserver* observer, 280 StatsCounterObserver* observer,
216 bool include_empty_intervals) 281 bool include_empty_intervals)
217 : StatsCounter(clock, include_empty_intervals, observer) {} 282 : StatsCounter(clock, include_empty_intervals, observer) {}
218 283
219 void RateAccCounter::Set(int sample) { 284 void RateAccCounter::Set(int sample) {
220 StatsCounter::Set(sample); 285 StatsCounter::Set(sample);
221 } 286 }
222 287
223 bool RateAccCounter::GetMetric(int* metric) const { 288 bool RateAccCounter::GetMetric(int* metric) const {
224 if (num_samples_ == 0 || last_sum_ > sum_) 289 if (num_samples_ == 0 || last_sum_ > sum_)
225 return false; 290 return false;
226 *metric = 291 *metric =
227 ((sum_ - last_sum_) * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; 292 ((sum_ - last_sum_) * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs;
228 return true; 293 return true;
229 } 294 }
230 295
296 int RateAccCounter::GetValueForEmptyInterval() const {
297 return 0;
298 }
299
231 } // namespace webrtc 300 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/video/stats_counter.h ('k') | webrtc/video/stats_counter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698