A Discrete-Event Network Simulator
API
windowed-filter.h
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2016 The Chromium Authors. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * Note: This code is modified to work under ns-3's environment.
34 * Modified by: Vivek Jain <jain.vivek.anand@gmail.com>
35 * Viyom Mittal <viyommittal@gmail.com>
36 * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
37 */
38
39// Implements Kathleen Nichols' algorithm for tracking the minimum (or maximum)
40// estimate of a stream of samples over some fixed time interval. (E.g.,
41// the minimum RTT over the past five minutes.) The algorithm keeps track of
42// the best, second best, and third best min (or max) estimates, maintaining an
43// invariant that the measurement time of the n'th best >= n-1'th best.
44// The algorithm works as follows. On a reset, all three estimates are set to
45// the same sample. The second best estimate is then recorded in the second
46// quarter of the window, and a third best estimate is recorded in the second
47// half of the window, bounding the worst case error when the true min is
48// monotonically increasing (or true max is monotonically decreasing) over the
49// window.
50//
51// A new best sample replaces all three estimates, since the new best is lower
52// (or higher) than everything else in the window and it is the most recent.
53// The window thus effectively gets reset on every new min. The same property
54// holds true for second best and third best estimates. Specifically, when a
55// sample arrives that is better than the second best but not better than the
56// best, it replaces the second and third best estimates but not the best
57// estimate. Similarly, a sample that is better than the third best estimate
58// but not the other estimates replaces only the third best estimate.
59//
60// Finally, when the best expires, it is replaced by the second best, which in
61// turn is replaced by the third best. The newest sample replaces the third
62// best.
63
64#ifndef WINDOWED_FILTER_H_
65#define WINDOWED_FILTER_H_
66
67namespace ns3 {
72template <class T>
74{
75public:
83 bool operator() (const T& lhs, const T& rhs) const
84 {
85 if (rhs == 0 || lhs == 0)
86 {
87 return false;
88 }
89 return lhs <= rhs;
90 }
91};
96template <class T>
98{
99public:
107 bool operator() (const T& lhs, const T& rhs) const
108 {
109 if (rhs == 0 || lhs == 0)
110 {
111 return false;
112 }
113 return lhs >= rhs;
114 }
115};
132template <class T, class Compare, typename TimeT, typename TimeDeltaT>
134{
135public:
140 {
141 }
142
150 WindowedFilter (TimeDeltaT windowLength, T zeroValue, TimeT zeroTime)
151 : m_windowLength (windowLength),
152 m_zeroValue (zeroValue),
154 {
155 Sample (m_zeroValue, zeroTime),
156 Sample (m_zeroValue, zeroTime),
157 Sample (m_zeroValue, zeroTime)
158 } {}
163 void SetWindowLength (TimeDeltaT windowLength)
164 {
165 m_windowLength = windowLength;
166 }
174 void Update (T new_sample, TimeT new_time)
175 {
176 // Reset all estimates if they have not yet been initialized, if new sample
177 // is a new best, or if the newest recorded estimate is too old.
178 if (m_samples[0].sample == m_zeroValue
179 || Compare () (new_sample, m_samples[0].sample)
180 || new_time - m_samples[2].time > m_windowLength)
181 {
182 Reset (new_sample, new_time);
183 return;
184 }
185 if (Compare () (new_sample, m_samples[1].sample))
186 {
187 m_samples[1] = Sample (new_sample, new_time);
188 m_samples[2] = m_samples[1];
189 }
190 else if (Compare () (new_sample, m_samples[2].sample))
191 {
192 m_samples[2] = Sample (new_sample, new_time);
193 }
194 // Expire and update estimates as necessary.
195 if (new_time - m_samples[0].time > m_windowLength)
196 {
197 // The best estimate hasn't been updated for an entire window, so promote
198 // second and third best estimates.
199 m_samples[0] = m_samples[1];
200 m_samples[1] = m_samples[2];
201 m_samples[2] = Sample (new_sample, new_time);
202 // Need to iterate one more time. Check if the new best estimate is
203 // outside the window as well, since it may also have been recorded a
204 // long time ago. Don't need to iterate once more since we cover that
205 // case at the beginning of the method.
206 if (new_time - m_samples[0].time > m_windowLength)
207 {
208 m_samples[0] = m_samples[1];
209 m_samples[1] = m_samples[2];
210 }
211 return;
212 }
213 if (m_samples[1].sample == m_samples[0].sample
214 && new_time - m_samples[1].time > m_windowLength >> 2)
215 {
216 // A quarter of the window has passed without a better sample, so the
217 // second-best estimate is taken from the second quarter of the window.
218 m_samples[2] = m_samples[1] = Sample (new_sample, new_time);
219 return;
220 }
221 if (m_samples[2].sample == m_samples[1].sample
222 && new_time - m_samples[2].time > m_windowLength >> 1)
223 {
224 // We've passed a half of the window without a better estimate, so take
225 // a third-best estimate from the second half of the window.
226 m_samples[2] = Sample (new_sample, new_time);
227 }
228 }
229
235 void Reset (T new_sample, TimeT new_time)
236 {
237 m_samples[0] = m_samples[1] = m_samples[2] = Sample (new_sample, new_time);
238 }
239
244 T GetBest () const
245 {
246 return m_samples[0].sample;
247 }
248
253 T GetSecondBest () const
254 {
255 return m_samples[1].sample;
256 }
257
262 T GetThirdBest () const
263 {
264 return m_samples[2].sample;
265 }
266
270 struct Sample
271 {
273 TimeT time;
278 {
279 }
280
286 Sample (T init_sample, TimeT init_time)
287 : sample (init_sample),
288 time (init_time)
289 {
290 }
291 };
292
293 TimeDeltaT m_windowLength;
296};
297
298} // namespace ns3
299#endif // WINDOWED_FILTER_H_
Construct a windowed filter.
WindowedFilter(TimeDeltaT windowLength, T zeroValue, TimeT zeroTime)
contructor
void Update(T new_sample, TimeT new_time)
Updates best estimates with |sample|, and expires and updates best estimates as necessary.
T GetSecondBest() const
Returns second Max/Min value so far among the windowed samples.
WindowedFilter()
contructor
Sample m_samples[3]
Best estimate is element 0.
T m_zeroValue
Uninitialized value of T.
TimeDeltaT m_windowLength
Time length of window.
T GetBest() const
Returns Max/Min value so far among the windowed samples.
T GetThirdBest() const
Returns third Max/Min value so far among the windowed samples.
void SetWindowLength(TimeDeltaT windowLength)
Changes the window length.
void Reset(T new_sample, TimeT new_time)
Resets all estimates to new sample.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Compares two values.
bool operator()(const T &lhs, const T &rhs) const
Compares two values.
Compares two values.
bool operator()(const T &lhs, const T &rhs) const
Compares two values.
Sample(T init_sample, TimeT init_time)
constructor
TimeT time
time when the sample was recorded.