OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | |
3 * | |
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 | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/base/bucketratetracker.h" | |
12 | |
13 #include <assert.h> | |
14 | |
15 #include "webrtc/base/timeutils.h" | |
16 | |
17 namespace rtc { | |
18 | |
19 BucketRateTracker::BucketRateTracker( | |
20 uint32 bucket_milliseconds, uint32 interval_buckets) | |
21 : bucket_milliseconds_(bucket_milliseconds), | |
22 interval_buckets_(interval_buckets), | |
23 unit_buckets_(new size_t[interval_buckets + 1]), | |
24 bucket_start_time_(~0u) { | |
25 assert(bucket_milliseconds > 0u); | |
26 assert(interval_buckets > 0u); | |
27 assert(bucket_milliseconds * interval_buckets >= 1000u); | |
28 } | |
29 | |
30 BucketRateTracker::~BucketRateTracker() { | |
31 delete[] unit_buckets_; | |
32 } | |
33 | |
34 size_t BucketRateTracker::units_second() const { | |
35 if (bucket_start_time_ == ~0u) { | |
36 return 0u; | |
37 } | |
38 uint32 current_time = Time(); | |
39 // Calculate which buckets to sum up given the current time. If the time | |
40 // has passed to a new bucket then we have to skip some of the oldest buckets. | |
41 uint32 interval_milliseconds = bucket_milliseconds_ * interval_buckets_; | |
noahric
2015/08/07 23:56:38
Yeah, this would be handy to pass in, and then it'
tpsiaki
2015/08/11 18:33:26
Done.
| |
42 // number of old buckets (i.e. after the current bucket in the ring buffer) | |
43 // that are expired given our current time interval. | |
44 uint32 buckets_to_skip; | |
45 // Number of milliseconds of the first bucket that are not a portion of the | |
46 // current interval. | |
47 uint32 milliseconds_to_skip; | |
48 if (current_time > initialization_time_ + interval_milliseconds) { | |
49 uint32 time_to_skip = current_time - bucket_start_time_;; | |
noahric
2015/08/07 23:56:38
extra ;
tpsiaki
2015/08/11 18:33:27
Done.
| |
50 buckets_to_skip = time_to_skip / bucket_milliseconds_; | |
51 milliseconds_to_skip = time_to_skip % bucket_milliseconds_; | |
52 } else { | |
53 buckets_to_skip = interval_buckets_ - current_bucket_; | |
54 milliseconds_to_skip = 0u; | |
55 interval_milliseconds = current_time - initialization_time_; | |
56 } | |
57 // If we're skipping all buckets that means that there have been no units | |
58 // within the sampling interval so report 0. For parity with RateTracker we | |
59 // also do not report for intervals under 1 second. | |
60 if (buckets_to_skip > interval_buckets_ || interval_milliseconds < 1000u) { | |
61 return 0u; | |
62 } | |
63 uint32 start_bucket = (current_bucket_ + 1 + buckets_to_skip) % | |
64 (interval_buckets_ + 1); | |
65 // Only count a portion of the first bucket according to how much of the | |
66 // first bucket is within the current interval. | |
67 size_t total_units = unit_buckets_[start_bucket] * | |
noahric
2015/08/07 23:56:38
Yeah, consider using "sample" as a substitute for
tpsiaki
2015/08/11 18:33:27
Done.
| |
68 (bucket_milliseconds_ - milliseconds_to_skip) / | |
69 bucket_milliseconds_; | |
70 // All other buckets in the interval are counted in their entirety. | |
71 for (uint32 i = (start_bucket + 1) % (interval_buckets_ + 1); | |
noahric
2015/08/07 23:56:38
size_t for indices (throughout)
noahric
2015/08/07 23:56:38
Consider a helper method like NextBucketIndex(size
tpsiaki
2015/08/11 18:33:27
Done.
tpsiaki
2015/08/11 18:33:27
Done.
| |
72 i != (current_bucket_ + 1) % (interval_buckets_ + 1); | |
73 i = (i + 1) % (interval_buckets_ + 1)) { | |
74 total_units += unit_buckets_[i]; | |
75 } | |
76 // Convert to units per second. | |
77 return (total_units * 1000 + (interval_milliseconds >> 1)) / | |
78 interval_milliseconds; | |
79 } | |
80 | |
81 void BucketRateTracker::Update(size_t units) { | |
82 EnsureInitialized(); | |
83 uint32 current_time = Time(); | |
84 // Advance the current bucket as needed for the current time, and reset | |
85 // bucket counts as we advance. | |
86 while (current_time > bucket_start_time_ + bucket_milliseconds_) { | |
noahric
2015/08/07 23:56:38
I'd replace this with a for loop, so you don't acc
tpsiaki
2015/08/11 18:33:27
Done.
| |
87 bucket_start_time_ += bucket_milliseconds_; | |
88 current_bucket_ = (current_bucket_ + 1u) % (interval_buckets_ + 1u); | |
89 unit_buckets_[current_bucket_] = 0u; | |
90 } | |
91 // Add all units in the bucket that includes the current time. | |
92 unit_buckets_[current_bucket_] += units; | |
93 } | |
94 | |
95 uint32 BucketRateTracker::Time() const { | |
96 return rtc::Time(); | |
97 } | |
98 | |
99 void BucketRateTracker::EnsureInitialized() { | |
100 if (bucket_start_time_ == ~0u) { | |
101 initialization_time_ = Time(); | |
102 bucket_start_time_ = initialization_time_; | |
103 current_bucket_ = 0u; | |
104 // We only need to initialize the first bucket because we reset buckets when | |
105 // current_bucket_ increments. | |
106 unit_buckets_[current_bucket_] = 0u; | |
107 } | |
108 } | |
109 | |
110 } // namespace rtc | |
OLD | NEW |