use crate::metrics::ORDER;
use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize};
pub struct EWMA {
uncounted: AtomicUsize,
alpha: f64,
rate: AtomicU64,
init: AtomicBool,
}
impl EWMA {
pub fn new(n: f64) -> Self {
EWMA::new_with_alpha(1.0 - (-5.0 / 60.0 / n).exp())
}
fn new_with_alpha(alpha: f64) -> Self {
EWMA {
uncounted: AtomicUsize::new(0),
alpha,
rate: AtomicU64::new(0),
init: AtomicBool::new(false),
}
}
pub fn rate(&self) -> f64 { f64::from_bits(self.rate.load(ORDER)) * 1e9 }
pub fn update(&self, n: usize) { self.uncounted.fetch_add(n, ORDER); }
pub fn tick(&self) {
let count = self.uncounted.swap(0, ORDER) as f64;
let instant_rate = count / 5e9;
if let Err(true) = self.init.compare_exchange(false, true, ORDER, ORDER)
{
let mut current_rate = f64::from_bits(self.rate.load(ORDER));
current_rate += self.alpha * (instant_rate - current_rate);
self.rate.store(f64::to_bits(current_rate), ORDER);
} else {
self.rate.store(f64::to_bits(instant_rate), ORDER);
}
}
}