1use std::collections::VecDeque;
25use std::time::{Instant, Duration};
26use std::ops::AddAssign;
27use std::iter::Sum;
28use std::default::Default;
29
30pub trait TimeInstant {
32 fn duration_since(&self, since: Self) -> Duration;
34 fn forward(&mut self, duration: Duration);
36}
37
38pub trait TimeSource {
40 type Instant: TimeInstant + Copy;
42 fn now(&self) -> Self::Instant;
44}
45
46impl TimeInstant for Instant {
47 fn duration_since(&self, earlier: Self) -> Duration {
48 self.duration_since(earlier)
49 }
50
51 fn forward(&mut self, duration: Duration) {
52 *self += duration;
53 }
54}
55
56#[derive(Debug)]
58pub struct RealTimeSource;
59impl TimeSource for RealTimeSource {
60 type Instant = Instant;
61
62 fn now(&self) -> Self::Instant {
63 Instant::now()
64 }
65}
66
67fn dts(duration: Duration) -> f64 {
68 duration.as_secs() as f64 + duration.subsec_nanos() as f64 * 1e-9
69}
70
71fn std(seconds: f64) -> Duration {
72 assert!(seconds >= 0.0, "RunningAverage negative duration - time going backwards?");
73 Duration::new(seconds.floor() as u64, ((seconds - seconds.floor()) * 1e-9) as u32)
74}
75
76impl TimeInstant for f64 {
77 fn duration_since(&self, earlier: Self) -> Duration {
78 std(self - earlier)
79 }
80
81 fn forward(&mut self, duration: Duration) {
82 *self += dts(duration);
83 }
84}
85
86#[derive(Debug)]
88pub struct ManualTimeSource {
89 now: f64,
90}
91
92impl TimeSource for ManualTimeSource {
93 type Instant = f64;
94
95 fn now(&self) -> Self::Instant {
96 self.now
97 }
98}
99
100impl ManualTimeSource {
101 pub fn new() -> ManualTimeSource {
102 ManualTimeSource {
103 now: 0.0
104 }
105 }
106
107 pub fn time_shift(&mut self, seconds: f64) {
108 self.now += seconds;
109 }
110}
111
112#[derive(Debug)]
114pub struct Measurement<T> {
115 value: T,
116 duration: Duration,
117}
118
119use std::fmt;
120impl<T> fmt::Display for Measurement<T> where T: Clone + fmt::Display + ToRate, <T as ToRate>::Output: Into<f64> {
121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122 write!(f, "{:.3}", self.rate().into())
123 }
124}
125
126impl<T> Measurement<T> {
127 pub fn value(&self) -> &T {
129 &self.value
130 }
131
132 pub fn unwrap(self) -> T {
134 self.value
135 }
136
137 pub fn rate(&self) -> <T as ToRate>::Output where T: Clone + ToRate {
139 self.value.clone().to_rate(self.duration)
140 }
141
142 pub fn to_rate(self) -> <T as ToRate>::Output where T: ToRate {
144 self.value.to_rate(self.duration)
145 }
146}
147
148#[derive(Debug)]
151pub struct RunningAverage<V: Default, I: TimeInstant + Copy> {
152 window: VecDeque<V>,
153 front: Option<I>,
154 duration: Duration,
155}
156
157impl<V: Default, I: TimeInstant + Copy> Default for RunningAverage<V, I> {
158 fn default() -> RunningAverage<V, I> {
160 RunningAverage::new(Duration::from_secs(8))
161 }
162}
163
164impl<V: Default, I: TimeInstant + Copy> RunningAverage<V, I> {
165 pub fn new(duration: Duration) -> RunningAverage<V, I> {
167 RunningAverage::with_capacity(duration, 16)
168 }
169
170 pub fn with_capacity(duration: Duration, capacity: usize) -> RunningAverage<V, I> {
172 assert!(capacity > 0, "RunningAverage capacity cannot be 0");
173 RunningAverage {
174 window: (0..capacity).map(|_| V::default()).collect(),
175 front: None,
176 duration: duration,
177 }
178 }
179
180 fn shift(&mut self, now: I) {
181 let front = self.front.get_or_insert(now);
182 let slot_duration = self.duration / self.window.len() as u32;
183 let mut slots_to_go = self.window.len();
184
185 while now.duration_since(*front) >= slot_duration {
186 if slots_to_go == 0 {
188 let since_front = now.duration_since(*front);
189 front.forward(since_front);
190 break;
191 }
192 self.window.pop_back();
193 self.window.push_front(V::default());
194 front.forward(slot_duration);
195 slots_to_go -= 1;
196 }
197 }
198
199 pub fn insert(&mut self, now: I, val: V) where V: AddAssign<V> {
202 self.shift(now);
203 *self.window.front_mut().unwrap() += val;
204 }
205
206 pub fn measurement<'i>(&'i mut self, now: I) -> Measurement<V> where V: Sum<&'i V> {
209 self.shift(now);
210
211 Measurement {
212 value: self.window.iter().sum(),
213 duration: self.duration,
214 }
215 }
216}
217
218#[derive(Debug)]
221pub struct RealTimeRunningAverage<V: Default, TS: TimeSource = RealTimeSource> {
222 inner: RunningAverage<V, TS::Instant>,
223 time_source: TS,
224}
225
226impl<V: Default> Default for RealTimeRunningAverage<V, RealTimeSource> {
227 fn default() -> RealTimeRunningAverage<V, RealTimeSource> {
228 RealTimeRunningAverage::new(Duration::from_secs(8))
229 }
230}
231
232impl<V: Default> RealTimeRunningAverage<V, RealTimeSource> {
233 pub fn new(duration: Duration) -> RealTimeRunningAverage<V, RealTimeSource> {
236 let time_source = RealTimeSource;
237
238 RealTimeRunningAverage {
239 inner: RunningAverage::new(duration),
240 time_source,
241 }
242 }
243}
244
245impl<V: Default, TS: TimeSource> RealTimeRunningAverage<V, TS> {
246 pub fn with_time_source(duration: Duration, capacity: usize, time_source: TS) -> RealTimeRunningAverage<V, TS> {
248 RealTimeRunningAverage {
249 inner: RunningAverage::with_capacity(duration, capacity),
250 time_source,
251 }
252 }
253
254 pub fn insert(&mut self, val: V) where V: AddAssign<V> {
257 let now = self.time_source.now();
258 self.inner.insert(now, val)
259 }
260
261 pub fn measurement<'i>(&'i mut self) -> Measurement<V> where V: Sum<&'i V> {
264 let now = self.time_source.now();
265 self.inner.measurement(now)
266 }
267
268 pub fn time_source(&mut self) -> &mut TS {
270 &mut self.time_source
271 }
272}
273
274pub trait ToRate {
278 type Output;
279 fn to_rate(self, duration: Duration) -> Self::Output;
280}
281
282impl<T: Into<f64>> ToRate for T {
283 type Output = f64;
284
285 fn to_rate(self, duration: Duration) -> f64 {
286 let v: f64 = self.into();
287 v / dts(duration)
288 }
289}
290
291#[cfg(test)]
292mod tests {
293 #[test]
294 fn const_over_different_capacity() {
295 use super::*;
296
297 for capacity in 1..31 {
298 let mut tw = RealTimeRunningAverage::with_time_source(Duration::from_secs(4), capacity, ManualTimeSource::new());
299
300 tw.insert(10);
301 tw.time_source().time_shift(1.0);
302 tw.insert(10);
303 tw.time_source().time_shift(1.0);
304 tw.insert(10);
305 tw.time_source().time_shift(1.0);
306 tw.insert(10);
307
308 assert_eq!(tw.measurement().unwrap(), 40, "for capacity {}: {:?}", capacity, tw);
309 assert_eq!(tw.measurement().to_rate(), 10.0, "for capacity {}: {:?}", capacity, tw);
310 }
311 }
312
313 #[test]
314 fn const_half_time_over_different_capacity() {
315 use super::*;
316
317 for capacity in 1..31 {
318 let mut tw = RealTimeRunningAverage::with_time_source(Duration::from_secs(4), capacity, ManualTimeSource::new());
319
320 tw.insert(10);
321 tw.time_source().time_shift(1.0);
322 tw.insert(10);
323 tw.time_source().time_shift(1.0);
324 tw.time_source().time_shift(1.0);
325
326 assert_eq!(tw.measurement().unwrap(), 20, "for capacity {}: {:?}", capacity, tw);
327 assert_eq!(tw.measurement().to_rate(), 5.0, "for capacity {}: {:?}", capacity, tw);
328 }
329 }
330
331 #[test]
332 fn default_int() {
333 use super::*;
334
335 let mut tw = RealTimeRunningAverage::default();
336
337 tw.insert(10);
338 tw.insert(10);
339
340 assert_eq!(tw.measurement().unwrap(), 20, "default: {:?}", tw);
342 assert_eq!(tw.measurement().to_rate(), 2.5, "default: {:?}", tw);
343 }
344
345 #[test]
346 fn default_f64() {
347 use super::*;
348
349 let mut tw = RealTimeRunningAverage::default();
350
351 tw.insert(10f64);
352 tw.insert(10.0);
353
354 assert_eq!(tw.measurement().unwrap(), 20.0, "default: {:?}", tw);
356 assert_eq!(tw.measurement().to_rate(), 2.5, "default: {:?}", tw);
357 }
358
359 #[test]
360 fn long_time_shift() {
361 use super::*;
362
363 let mut tw = RealTimeRunningAverage::with_time_source(Duration::from_secs(4), 16, ManualTimeSource::new());
364
365 tw.insert(10);
366 tw.time_source().time_shift(1_000_000_000.0);
367 tw.insert(10);
368 tw.time_source().time_shift(1.0);
369 tw.insert(10);
370 tw.time_source().time_shift(1.0);
371 tw.insert(10);
372 tw.time_source().time_shift(1.0);
373 tw.insert(10);
374
375 assert_eq!(tw.measurement().unwrap(), 40, "long: {:?}", tw);
376 assert_eq!(tw.measurement().to_rate(), 10.0, "long: {:?}", tw);
377 }
378
379 #[test]
380 fn measurement_display() {
381 use super::*;
382
383 let mut tw = RealTimeRunningAverage::default();
384
385 tw.insert(10);
386 tw.insert(10);
387
388 assert_eq!(&format!("{}", tw.measurement()), "2.500");
389 }
390}