| Index: net/quic/congestion_control/windowed_filter.h
|
| diff --git a/net/quic/congestion_control/windowed_filter.h b/net/quic/congestion_control/windowed_filter.h
|
| deleted file mode 100644
|
| index 50a6b1c2fd4ab2b64cb1583f2b47ed4e1ef5e22c..0000000000000000000000000000000000000000
|
| --- a/net/quic/congestion_control/windowed_filter.h
|
| +++ /dev/null
|
| @@ -1,156 +0,0 @@
|
| -// Copyright (c) 2016 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.
|
| -//
|
| -#ifndef NET_QUIC_CONGESTION_CONTROL_WINDOWED_FILTER_H_
|
| -#define NET_QUIC_CONGESTION_CONTROL_WINDOWED_FILTER_H_
|
| -
|
| -// Implements Kathleen Nichols' algorithm for tracking the minimum (or maximum)
|
| -// estimate of a stream of samples over some fixed time interval. (E.g.,
|
| -// the minimum RTT over the past five minutes.) The algorithm keeps track of
|
| -// the best, second best, and third best min (or max) estimates, maintaining an
|
| -// invariant that the measurement time of the n'th best >= n-1'th best.
|
| -
|
| -// The algorithm works as follows. On a reset, all three estimates are set to
|
| -// the same sample. The second best estimate is then recorded in the second
|
| -// quarter of the window, and a third best estimate is recorded in the second
|
| -// half of the window, bounding the worst case error when the true min is
|
| -// monotonically increasing (or true max is monotonically decreasing) over the
|
| -// window.
|
| -//
|
| -// A new best sample replaces all three estimates, since the new best is lower
|
| -// (or higher) than everything else in the window and it is the most recent.
|
| -// The window thus effectively gets reset on every new min. The same property
|
| -// holds true for second best and third best estimates. Specifically, when a
|
| -// sample arrives that is better than the second best but not better than the
|
| -// best, it replaces the second and third best estimates but not the best
|
| -// estimate. Similarly, a sample that is better than the third best estimate
|
| -// but not the other estimates replaces only the third best estimate.
|
| -//
|
| -// Finally, when the best expires, it is replaced by the second best, which in
|
| -// turn is replaced by the third best. The newest sample replaces the third
|
| -// best.
|
| -
|
| -#include "base/logging.h"
|
| -#include "net/quic/quic_time.h"
|
| -
|
| -namespace net {
|
| -
|
| -// Compares two values and returns true if the first is less than or equal
|
| -// to the second.
|
| -template <class T>
|
| -struct MinFilter {
|
| - bool operator()(const T& lhs, const T& rhs) const { return lhs <= rhs; }
|
| -};
|
| -
|
| -// Compares two values and returns true if the first is greater than or equal
|
| -// to the second.
|
| -template <class T>
|
| -struct MaxFilter {
|
| - bool operator()(const T& lhs, const T& rhs) const { return lhs >= rhs; }
|
| -};
|
| -
|
| -// Use the following to construct a windowed filter object of type T.
|
| -// For example, a min filter using QuicTime as the time type:
|
| -// WindowedFilter<T, MinFilter<T>, QuicTime, QuicTime::Delta> ObjectName;
|
| -// A max filter using 64-bit integers as the time type:
|
| -// WindowedFilter<T, MaxFilter<T>, uint64_t, int64_t> ObjectName;
|
| -// Specifically, this template takes four arguments:
|
| -// 1. T -- type of the measurement that is being filtered.
|
| -// 2. Compare -- MinFilter<T> or MaxFilter<T>, depending on the type of filter
|
| -// desired.
|
| -// 3. TimeT -- the type used to represent timestamps.
|
| -// 4. TimeDeltaT -- the type used to represent continuous time intervals between
|
| -// two timestamps. Has to be the type of (a - b) if both |a| and |b| are
|
| -// of type TimeT.
|
| -template <class T, class Compare, typename TimeT, typename TimeDeltaT>
|
| -class WindowedFilter {
|
| - public:
|
| - // |window_length| is the period after which a best estimate expires.
|
| - // |zero_value| is used as the uninitialized value for objects of T.
|
| - // Importantly, |zero_value| should be an invalid value for a true sample.
|
| - WindowedFilter(TimeDeltaT window_length, T zero_value, TimeT zero_time)
|
| - : window_length_(window_length),
|
| - zero_value_(zero_value),
|
| - estimates_{Sample(zero_value_, zero_time),
|
| - Sample(zero_value_, zero_time),
|
| - Sample(zero_value_, zero_time)} {}
|
| -
|
| - // Updates best estimates with |sample|, and expires and updates best
|
| - // estimates as necessary.
|
| - void Update(T new_sample, TimeT new_time) {
|
| - // Reset all estimates if they have not yet been initialized, if new sample
|
| - // is a new best, or if the newest recorded estimate is too old.
|
| - if (estimates_[0].sample == zero_value_ ||
|
| - Compare()(new_sample, estimates_[0].sample) ||
|
| - new_time - estimates_[2].time > window_length_) {
|
| - Reset(new_sample, new_time);
|
| - return;
|
| - }
|
| -
|
| - if (Compare()(new_sample, estimates_[1].sample)) {
|
| - estimates_[1] = Sample(new_sample, new_time);
|
| - estimates_[2] = estimates_[1];
|
| - } else if (Compare()(new_sample, estimates_[2].sample)) {
|
| - estimates_[2] = Sample(new_sample, new_time);
|
| - }
|
| -
|
| - // Expire and update estimates as necessary.
|
| - if (new_time - estimates_[0].time > window_length_) {
|
| - // The best estimate hasn't been updated for an entire window, so promote
|
| - // second and third best estimates.
|
| - estimates_[0] = estimates_[1];
|
| - estimates_[1] = estimates_[2];
|
| - estimates_[2] = Sample(new_sample, new_time);
|
| - // Need to iterate one more time. Check if the new best estimate is
|
| - // outside the window as well, since it may also have been recorded a
|
| - // long time ago. Don't need to iterate once more since we cover that
|
| - // case at the beginning of the method.
|
| - if (new_time - estimates_[0].time > window_length_) {
|
| - estimates_[0] = estimates_[1];
|
| - estimates_[1] = estimates_[2];
|
| - }
|
| - return;
|
| - }
|
| - if (estimates_[1].sample == estimates_[0].sample &&
|
| - new_time - estimates_[1].time > window_length_ >> 2) {
|
| - // A quarter of the window has passed without a better sample, so the
|
| - // second-best estimate is taken from the second quarter of the window.
|
| - estimates_[2] = estimates_[1] = Sample(new_sample, new_time);
|
| - return;
|
| - }
|
| -
|
| - if (estimates_[2].sample == estimates_[1].sample &&
|
| - new_time - estimates_[2].time > window_length_ >> 1) {
|
| - // We've passed a half of the window without a better estimate, so take
|
| - // a third-best estimate from the second half of the window.
|
| - estimates_[2] = Sample(new_sample, new_time);
|
| - }
|
| - }
|
| -
|
| - // Resets all estimates to new sample.
|
| - void Reset(T new_sample, TimeT new_time) {
|
| - estimates_[0] = estimates_[1] = estimates_[2] =
|
| - Sample(new_sample, new_time);
|
| - }
|
| -
|
| - T GetBest() const { return estimates_[0].sample; }
|
| - T GetSecondBest() const { return estimates_[1].sample; }
|
| - T GetThirdBest() const { return estimates_[2].sample; }
|
| -
|
| - private:
|
| - struct Sample {
|
| - T sample;
|
| - TimeT time;
|
| - Sample(T init_sample, TimeT init_time)
|
| - : sample(init_sample), time(init_time) {}
|
| - };
|
| -
|
| - TimeDeltaT window_length_; // Time length of window.
|
| - T zero_value_; // Uninitialized value of T.
|
| - Sample estimates_[3]; // Best estimate is element 0.
|
| -};
|
| -
|
| -} // namespace net
|
| -
|
| -#endif // NET_QUIC_CONGESTION_CONTROL_WINDOWED_FILTER_H_
|
|
|