use std::time::{Duration, Instant};
const NUM_SAMPLES: usize = 10;
#[derive(Default)]
pub struct Meter {
times: [f64; NUM_SAMPLES],
avg: f64,
index: usize,
}
pub struct Sampler<'a> {
meter: &'a mut Meter,
created_at: Instant,
}
impl<'a> Sampler<'a> {
fn new(meter: &'a mut Meter) -> Sampler<'a> {
Sampler { meter, created_at: Instant::now() }
}
#[inline]
fn alive_duration(&self) -> Duration {
self.created_at.elapsed()
}
}
impl<'a> Drop for Sampler<'a> {
fn drop(&mut self) {
self.meter.add_sample(self.alive_duration());
}
}
impl Meter {
pub fn new() -> Meter {
Default::default()
}
pub fn sampler(&mut self) -> Sampler<'_> {
Sampler::new(self)
}
pub fn average(&self) -> f64 {
self.avg
}
fn add_sample(&mut self, sample: Duration) {
let mut usec = 0f64;
usec += f64::from(sample.subsec_nanos()) / 1e3;
usec += (sample.as_secs() as f64) * 1e6;
let prev = self.times[self.index];
self.times[self.index] = usec;
self.avg -= prev / NUM_SAMPLES as f64;
self.avg += usec / NUM_SAMPLES as f64;
self.index = (self.index + 1) % NUM_SAMPLES;
}
}