summaryrefslogtreecommitdiff
path: root/content/browser/download/rate_estimator.cc
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-06-11 10:57:03 +0100
committerTorne (Richard Coles) <torne@google.com>2013-06-11 10:57:03 +0100
commit868fa2fe829687343ffae624259930155e16dbd8 (patch)
tree54d316199dd9739c57c3aacd131853bbd6554a94 /content/browser/download/rate_estimator.cc
parentbb1bdbd796f966b5bf11f40ecbea12621c7bfac9 (diff)
downloadchromium_org-868fa2fe829687343ffae624259930155e16dbd8.tar.gz
Merge from Chromium at DEPS revision r205460
This commit was generated by merge_to_master.py. Change-Id: I4a744a5e426bd3bb378d887cfa56fe054742a540
Diffstat (limited to 'content/browser/download/rate_estimator.cc')
-rw-r--r--content/browser/download/rate_estimator.cc122
1 files changed, 122 insertions, 0 deletions
diff --git a/content/browser/download/rate_estimator.cc b/content/browser/download/rate_estimator.cc
new file mode 100644
index 0000000000..dcdd71af41
--- /dev/null
+++ b/content/browser/download/rate_estimator.cc
@@ -0,0 +1,122 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/download/rate_estimator.h"
+
+#include "base/logging.h"
+
+using base::TimeDelta;
+using base::TimeTicks;
+
+namespace content {
+
+namespace {
+
+static const int kDefaultBucketTimeSeconds = 1;
+static const size_t kDefaultNumBuckets = 10;
+
+} // namespace
+
+RateEstimator::RateEstimator()
+ : history_(kDefaultNumBuckets),
+ bucket_time_(TimeDelta::FromSeconds(kDefaultBucketTimeSeconds)),
+ oldest_index_(0),
+ bucket_count_(1) {
+ ResetBuckets(TimeTicks::Now());
+}
+
+RateEstimator::RateEstimator(TimeDelta bucket_time,
+ size_t num_buckets,
+ TimeTicks now)
+ : history_(num_buckets),
+ bucket_time_(bucket_time),
+ oldest_index_(0),
+ bucket_count_(1) {
+ DCHECK(bucket_time_.InSeconds() > 0);
+ ResetBuckets(now);
+}
+
+RateEstimator::~RateEstimator() {
+}
+
+void RateEstimator::Increment(uint32 count) {
+ Increment(count, TimeTicks::Now());
+}
+
+void RateEstimator::Increment(uint32 count, TimeTicks now) {
+ ClearOldBuckets(now);
+ int64 seconds_since_oldest = (now - oldest_time_).InSeconds();
+ DCHECK(seconds_since_oldest >= 0);
+ int64 delta_buckets = seconds_since_oldest / bucket_time_.InSeconds();
+ DCHECK(delta_buckets >= 0);
+ size_t index_offset = static_cast<size_t>(delta_buckets);
+ DCHECK(index_offset <= history_.size());
+ int current_index = (oldest_index_ + delta_buckets) % history_.size();
+ history_[current_index] += count;
+}
+
+uint64 RateEstimator::GetCountPerSecond() const {
+ return GetCountPerSecond(TimeTicks::Now());
+}
+
+uint64 RateEstimator::GetCountPerSecond(TimeTicks now) const {
+ const_cast<RateEstimator*>(this)->ClearOldBuckets(now);
+ // TODO(cbentzel): Support fractional seconds for active bucket?
+ // We explicitly don't check for overflow here. If it happens, unsigned
+ // arithmetic at least guarantees behavior by wrapping around. The estimate
+ // will be off, but the code will still be valid.
+ uint64 total_count = 0;
+ for (size_t i = 0; i < bucket_count_; ++i) {
+ size_t index = (oldest_index_ + i) % history_.size();
+ total_count += history_[index];
+ }
+ return total_count / (bucket_count_ * bucket_time_.InSeconds());
+}
+
+void RateEstimator::ClearOldBuckets(TimeTicks now) {
+ int64 seconds_since_oldest = (now - oldest_time_).InSeconds();
+
+ int64 delta_buckets = seconds_since_oldest / bucket_time_.InSeconds();
+
+ // It's possible (although unlikely) for there to be rollover with TimeTicks.
+ // If that's the case, just reset the history.
+ if (delta_buckets < 0) {
+ ResetBuckets(now);
+ return;
+ }
+ size_t delta_index = static_cast<size_t>(delta_buckets);
+
+ // If we are within the current window, keep the existing data.
+ if (delta_index < history_.size()) {
+ bucket_count_ = delta_index + 1;
+ return;
+ }
+
+ // If it's been long enough that all history data is too stale, just
+ // clear all the buckets.
+ size_t extra_buckets = delta_index - history_.size() + 1;
+ if (extra_buckets > history_.size()) {
+ ResetBuckets(now);
+ return;
+ }
+
+ // Clear out stale buckets in the history.
+ bucket_count_ = history_.size();
+ for (size_t i = 0; i < extra_buckets; ++i) {
+ history_[oldest_index_] = 0;
+ oldest_index_ = (oldest_index_ + 1) % history_.size();
+ oldest_time_ = oldest_time_ + bucket_time_;
+ }
+}
+
+void RateEstimator::ResetBuckets(TimeTicks now) {
+ for (size_t i = 0; i < history_.size(); ++i) {
+ history_[i] = 0;
+ }
+ oldest_index_ = 0;
+ bucket_count_ = 1;
+ oldest_time_ = now;
+}
+
+} // namespace content