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

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: address comments 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
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 Empty() const { return stats_.num_samples == 0; }
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
86 AggregatedStats StatsCounter::ProcessAndGetStats() {
87 if (HasSample())
88 TryProcess();
89 return aggregated_counter_->ComputeStats();
90 }
91
92 void StatsCounter::ProcessAndPause() {
93 if (HasSample())
94 TryProcess();
95 paused_ = true;
96 }
97
77 bool StatsCounter::HasSample() const { 98 bool StatsCounter::HasSample() const {
78 return last_process_time_ms_ != -1; 99 return last_process_time_ms_ != -1;
79 } 100 }
80 101
81 bool StatsCounter::TimeToProcess() { 102 bool StatsCounter::TimeToProcess(int* elapsed_intervals) {
82 int64_t now = clock_->TimeInMilliseconds(); 103 int64_t now = clock_->TimeInMilliseconds();
83 if (last_process_time_ms_ == -1) 104 if (last_process_time_ms_ == -1)
84 last_process_time_ms_ = now; 105 last_process_time_ms_ = now;
85 106
86 int64_t diff_ms = now - last_process_time_ms_; 107 int64_t diff_ms = now - last_process_time_ms_;
87 if (diff_ms < kProcessIntervalMs) 108 if (diff_ms < kProcessIntervalMs)
88 return false; 109 return false;
89 110
90 // Advance number of complete kProcessIntervalMs that have passed. 111 // Advance number of complete kProcessIntervalMs that have passed.
91 int64_t num_intervals = diff_ms / kProcessIntervalMs; 112 int64_t num_intervals = diff_ms / kProcessIntervalMs;
92 last_process_time_ms_ += num_intervals * kProcessIntervalMs; 113 last_process_time_ms_ += num_intervals * kProcessIntervalMs;
93 114
94 // Add zero for intervals without samples. 115 *elapsed_intervals = num_intervals;
95 if (include_empty_intervals_) {
96 for (int64_t i = 0; i < num_intervals - 1; ++i) {
97 aggregated_counter_->Add(0);
98 if (observer_)
99 observer_->OnMetricUpdated(0);
100 }
101 }
102 return true; 116 return true;
103 } 117 }
104 118
105 void StatsCounter::Set(int sample) { 119 void StatsCounter::Set(int sample) {
106 TryProcess(); 120 TryProcess();
107 ++num_samples_; 121 ++num_samples_;
108 sum_ = sample; 122 sum_ = sample;
123 paused_ = false;
109 } 124 }
110 125
111 void StatsCounter::Add(int sample) { 126 void StatsCounter::Add(int sample) {
112 TryProcess(); 127 TryProcess();
113 ++num_samples_; 128 ++num_samples_;
114 sum_ += sample; 129 sum_ += sample;
115 130
116 if (num_samples_ == 1) 131 if (num_samples_ == 1)
117 max_ = sample; 132 max_ = sample;
118 max_ = std::max(sample, max_); 133 max_ = std::max(sample, max_);
134 paused_ = false;
135 }
136
137 // Reports periodically computed metric.
138 void StatsCounter::ReportMetricToAggregatedCounter(
139 int value,
140 int num_values_to_add) const {
141 for (int i = 0; i < num_values_to_add; ++i) {
142 aggregated_counter_->Add(value);
143 if (observer_)
144 observer_->OnMetricUpdated(value);
145 }
119 } 146 }
120 147
121 void StatsCounter::TryProcess() { 148 void StatsCounter::TryProcess() {
122 if (!TimeToProcess()) 149 int elapsed_intervals;
150 if (!TimeToProcess(&elapsed_intervals))
123 return; 151 return;
124 152
153 // Get and report periodically computed metric.
125 int metric; 154 int metric;
126 if (GetMetric(&metric)) { 155 if (GetMetric(&metric))
127 aggregated_counter_->Add(metric); 156 ReportMetricToAggregatedCounter(metric, 1);
128 if (observer_) 157
129 observer_->OnMetricUpdated(metric); 158 // Report value for elapsed intervals without samples.
159 if (IncludeEmptyIntervals()) {
160 // If there are no samples, all elapsed intervals are empty (otherwise one
161 // interval contains sample(s), discard this interval).
162 int empty_intervals =
163 (num_samples_ == 0) ? elapsed_intervals : (elapsed_intervals - 1);
164 ReportMetricToAggregatedCounter(GetValueForEmptyInterval(),
165 empty_intervals);
130 } 166 }
131 last_sum_ = sum_; 167
168 // Reset samples for elapsed interval.
169 if (num_samples_ > 0)
170 last_sum_ = sum_;
132 sum_ = 0; 171 sum_ = 0;
133 max_ = 0; 172 max_ = 0;
134 num_samples_ = 0; 173 num_samples_ = 0;
135 } 174 }
136 175
176 bool StatsCounter::IncludeEmptyIntervals() const {
177 return include_empty_intervals_ && !paused_ && !aggregated_counter_->Empty();
178 }
179
137 // StatsCounter sub-classes. 180 // StatsCounter sub-classes.
138 AvgCounter::AvgCounter(Clock* clock, StatsCounterObserver* observer) 181 AvgCounter::AvgCounter(Clock* clock,
139 : StatsCounter(clock, 182 StatsCounterObserver* observer,
140 false, // |include_empty_intervals| 183 bool include_empty_intervals)
141 observer) {} 184 : StatsCounter(clock, include_empty_intervals, observer) {}
142 185
143 void AvgCounter::Add(int sample) { 186 void AvgCounter::Add(int sample) {
144 StatsCounter::Add(sample); 187 StatsCounter::Add(sample);
145 } 188 }
146 189
147 bool AvgCounter::GetMetric(int* metric) const { 190 bool AvgCounter::GetMetric(int* metric) const {
148 if (num_samples_ == 0) 191 if (num_samples_ == 0)
149 return false; 192 return false;
150 *metric = (sum_ + num_samples_ / 2) / num_samples_; 193 *metric = (sum_ + num_samples_ / 2) / num_samples_;
151 return true; 194 return true;
152 } 195 }
153 196
197 int AvgCounter::GetValueForEmptyInterval() const {
198 return aggregated_counter_->last_sample();
199 }
200
154 MaxCounter::MaxCounter(Clock* clock, StatsCounterObserver* observer) 201 MaxCounter::MaxCounter(Clock* clock, StatsCounterObserver* observer)
155 : StatsCounter(clock, 202 : StatsCounter(clock,
156 false, // |include_empty_intervals| 203 false, // |include_empty_intervals|
157 observer) {} 204 observer) {}
158 205
159 void MaxCounter::Add(int sample) { 206 void MaxCounter::Add(int sample) {
160 StatsCounter::Add(sample); 207 StatsCounter::Add(sample);
161 } 208 }
162 209
163 bool MaxCounter::GetMetric(int* metric) const { 210 bool MaxCounter::GetMetric(int* metric) const {
164 if (num_samples_ == 0) 211 if (num_samples_ == 0)
165 return false; 212 return false;
166 *metric = max_; 213 *metric = max_;
167 return true; 214 return true;
168 } 215 }
169 216
217 int MaxCounter::GetValueForEmptyInterval() const {
218 RTC_NOTREACHED();
219 return 0;
220 }
221
170 PercentCounter::PercentCounter(Clock* clock, StatsCounterObserver* observer) 222 PercentCounter::PercentCounter(Clock* clock, StatsCounterObserver* observer)
171 : StatsCounter(clock, 223 : StatsCounter(clock,
172 false, // |include_empty_intervals| 224 false, // |include_empty_intervals|
173 observer) {} 225 observer) {}
174 226
175 void PercentCounter::Add(bool sample) { 227 void PercentCounter::Add(bool sample) {
176 StatsCounter::Add(sample ? 1 : 0); 228 StatsCounter::Add(sample ? 1 : 0);
177 } 229 }
178 230
179 bool PercentCounter::GetMetric(int* metric) const { 231 bool PercentCounter::GetMetric(int* metric) const {
180 if (num_samples_ == 0) 232 if (num_samples_ == 0)
181 return false; 233 return false;
182 *metric = (sum_ * 100 + num_samples_ / 2) / num_samples_; 234 *metric = (sum_ * 100 + num_samples_ / 2) / num_samples_;
183 return true; 235 return true;
184 } 236 }
185 237
238 int PercentCounter::GetValueForEmptyInterval() const {
239 RTC_NOTREACHED();
240 return 0;
241 }
242
186 PermilleCounter::PermilleCounter(Clock* clock, StatsCounterObserver* observer) 243 PermilleCounter::PermilleCounter(Clock* clock, StatsCounterObserver* observer)
187 : StatsCounter(clock, 244 : StatsCounter(clock,
188 false, // |include_empty_intervals| 245 false, // |include_empty_intervals|
189 observer) {} 246 observer) {}
190 247
191 void PermilleCounter::Add(bool sample) { 248 void PermilleCounter::Add(bool sample) {
192 StatsCounter::Add(sample ? 1 : 0); 249 StatsCounter::Add(sample ? 1 : 0);
193 } 250 }
194 251
195 bool PermilleCounter::GetMetric(int* metric) const { 252 bool PermilleCounter::GetMetric(int* metric) const {
196 if (num_samples_ == 0) 253 if (num_samples_ == 0)
197 return false; 254 return false;
198 *metric = (sum_ * 1000 + num_samples_ / 2) / num_samples_; 255 *metric = (sum_ * 1000 + num_samples_ / 2) / num_samples_;
199 return true; 256 return true;
200 } 257 }
201 258
259 int PermilleCounter::GetValueForEmptyInterval() const {
260 RTC_NOTREACHED();
261 return 0;
262 }
263
202 RateCounter::RateCounter(Clock* clock, 264 RateCounter::RateCounter(Clock* clock,
203 StatsCounterObserver* observer, 265 StatsCounterObserver* observer,
204 bool include_empty_intervals) 266 bool include_empty_intervals)
205 : StatsCounter(clock, include_empty_intervals, observer) {} 267 : StatsCounter(clock, include_empty_intervals, observer) {}
206 268
207 void RateCounter::Add(int sample) { 269 void RateCounter::Add(int sample) {
208 StatsCounter::Add(sample); 270 StatsCounter::Add(sample);
209 } 271 }
210 272
211 bool RateCounter::GetMetric(int* metric) const { 273 bool RateCounter::GetMetric(int* metric) const {
212 if (num_samples_ == 0) 274 if (num_samples_ == 0)
213 return false; 275 return false;
214 *metric = (sum_ * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; 276 *metric = (sum_ * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs;
215 return true; 277 return true;
216 } 278 }
217 279
280 int RateCounter::GetValueForEmptyInterval() const {
281 return 0;
282 }
283
218 RateAccCounter::RateAccCounter(Clock* clock, 284 RateAccCounter::RateAccCounter(Clock* clock,
219 StatsCounterObserver* observer, 285 StatsCounterObserver* observer,
220 bool include_empty_intervals) 286 bool include_empty_intervals)
221 : StatsCounter(clock, include_empty_intervals, observer) {} 287 : StatsCounter(clock, include_empty_intervals, observer) {}
222 288
223 void RateAccCounter::Set(int sample) { 289 void RateAccCounter::Set(int sample) {
224 StatsCounter::Set(sample); 290 StatsCounter::Set(sample);
225 } 291 }
226 292
227 bool RateAccCounter::GetMetric(int* metric) const { 293 bool RateAccCounter::GetMetric(int* metric) const {
228 if (num_samples_ == 0 || last_sum_ > sum_) 294 if (num_samples_ == 0 || last_sum_ > sum_)
229 return false; 295 return false;
230 *metric = 296 *metric =
231 ((sum_ - last_sum_) * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; 297 ((sum_ - last_sum_) * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs;
232 return true; 298 return true;
233 } 299 }
234 300
301 int RateAccCounter::GetValueForEmptyInterval() const {
302 return 0;
303 }
304
235 } // namespace webrtc 305 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698