Chromium Code Reviews| 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 |