use crate::all::{Duration, Rate};
use arraydeque::{ArrayDeque, Wrapping};
use core::cmp;
const NS_TO_S: f64 = 1e-9;
#[derive(Clone, Debug)]
pub struct RateStats {
avg_ring: ArrayDeque<[u64; 1024], Wrapping>,
avg_16: f64,
avg_128: f64,
avg_1024: f64,
max_ns_16: u64,
max_ns_128: u64,
max_ns_1024: u64,
}
impl Default for RateStats {
fn default() -> Self {
Self {
avg_ring: ArrayDeque::new(),
avg_16: 0.0,
avg_128: 0.0,
avg_1024: 0.0,
max_ns_16: 0,
max_ns_128: 0,
max_ns_1024: 0,
}
}
}
impl RateStats {
#[inline]
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn add(&mut self, duration: Duration) {
self.avg_ring
.push_back(cmp::max(0_i128, duration.whole_nanoseconds()) as u64);
}
#[inline]
pub fn add_ns(&mut self, nanoseconds: u64) {
self.avg_ring.push_back(nanoseconds);
}
pub fn update(&mut self, tick_count: u64) {
if tick_count % 16 == 0 {
let mut avg_accumulator = 0_u64;
self.max_ns_16 = 0;
let mut i = self.avg_ring.iter();
for _ in 0..16 {
let val = i.next_back().unwrap_or(&0);
avg_accumulator += i.next_back().unwrap_or(&0);
self.max_ns_16 = cmp::max(self.max_ns_16, *val);
}
self.avg_16 = avg_accumulator as f64 / 16.;
}
if tick_count % 128 == 0 {
let mut avg_accumulator = 0_u64;
self.max_ns_128 = 0;
let mut i = self.avg_ring.iter();
for _ in 0..128 {
let val = i.next_back().unwrap_or(&0);
avg_accumulator += val;
self.max_ns_128 = cmp::max(self.max_ns_128, *val);
}
self.avg_128 = avg_accumulator as f64 / 128.;
}
if tick_count % 1024 == 0 {
let mut avg_accumulator = 0_u64;
let mut i = self.avg_ring.iter();
self.max_ns_1024 = 0;
for _ in 0..1024 {
let val = i.next_back().unwrap_or(&0);
avg_accumulator += val;
self.max_ns_1024 = cmp::max(self.max_ns_1024, *val);
}
self.avg_1024 = avg_accumulator as f64 / 1024.;
}
}
pub fn reset(&mut self) {
self.avg_16 = 0.0;
self.avg_128 = 0.0;
self.avg_1024 = 0.0;
self.max_ns_128 = 0;
self.max_ns_1024 = 0;
}
pub fn log(&self, name: &str, rate: Option<&Rate>) {
let avg_16 = 1. / (self.avg_16 * NS_TO_S);
let avg_128 = 1. / (self.avg_128 * NS_TO_S);
let avg_1024 = 1. / (self.avg_1024 * NS_TO_S);
let min_16 = 1. / (self.max_ns_16 as f64 * NS_TO_S);
let min_128 = 1. / (self.max_ns_128 as f64 * NS_TO_S);
let min_1024 = 1. / (self.max_ns_1024 as f64 * NS_TO_S);
if let Some(rate) = rate {
let d = rate.duration();
let tps = rate.tps();
let pcta_16 = avg_16 / tps * 100.;
let pcta_128 = avg_128 / tps * 100.;
let pcta_1024 = avg_1024 / tps * 100.;
let pctm_16 = min_16 / tps * 100.;
let pctm_128 = min_128 / tps * 100.;
let pctm_1024 = min_1024 / tps * 100.;
log::trace![
"[window]avg(%)|min(%) rate tps:{tps:.2} dpt:{d} \"{name}\":
[16]{avg_16:.2}({pcta_16:.1}%)|{min_16:.2}({pctm_16:.1}%) \
[128]{avg_128:.2}({pcta_128:.1}%)|{min_128:.2}({pctm_128:.1}%) \
[1024]{avg_1024:.2}({pcta_1024:.1}%)|{min_1024:.2}({pctm_1024:.1}%)
"
];
} else {
let pctm_16 = min_16 / avg_16 * 100.;
let pctm_128 = min_128 / avg_128 * 100.;
let pctm_1024 = min_1024 / avg_1024 * 100.;
log::trace![
"[window]avg|min rate \"{name}\":
[16]{avg_16:.2}|{min_16:.2}({pctm_16:.1}%) \
[128]{avg_128:.2}|{min_128:.2}({pctm_128:.1}%) \
[1024]{avg_1024:.2}|{min_1024:.2}({pctm_1024:.1}%)
"
];
}
}
}