use std::ops::AddAssign;
#[derive(Clone, Copy, Debug, Default)]
pub struct ThruputCounters {
pub protocol: ChannelCounter,
pub payload: ChannelCounter,
pub waste: Counter,
}
impl ThruputCounters {
pub fn reset(&mut self) {
self.protocol.reset();
self.payload.reset();
self.waste.reset();
}
}
impl AddAssign<&ThruputCounters> for ThruputCounters {
fn add_assign(&mut self, rhs: &ThruputCounters) {
self.protocol += &rhs.protocol;
self.payload += &rhs.payload;
self.waste += rhs.waste.round();
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct ChannelCounter {
pub down: Counter,
pub up: Counter,
}
impl ChannelCounter {
pub fn reset(&mut self) {
self.down.reset();
self.up.reset();
}
}
impl AddAssign<&ChannelCounter> for ChannelCounter {
fn add_assign(&mut self, rhs: &ChannelCounter) {
self.down += rhs.down.round();
self.up += rhs.up.round();
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Counter {
total: u64,
round: u64,
avg: f64,
peak: f64,
}
impl Counter {
const WEIGHT: u64 = 5;
pub fn add(&mut self, bytes: u64) {
self.total += bytes;
self.round += bytes;
}
pub fn reset(&mut self) {
self.avg = (self.avg * (Self::WEIGHT - 1) as f64 / Self::WEIGHT as f64)
+ (self.round as f64 / Self::WEIGHT as f64);
self.round = 0;
if self.avg > self.peak {
self.peak = self.avg;
}
}
pub fn avg(&self) -> u64 {
self.avg.round() as u64
}
pub fn peak(&self) -> u64 {
self.peak.round() as u64
}
pub fn total(&self) -> u64 {
self.total
}
pub fn round(&self) -> u64 {
self.round
}
}
impl AddAssign<u64> for Counter {
fn add_assign(&mut self, rhs: u64) {
self.add(rhs);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_counter() {
let mut c = Counter::default();
assert_eq!(c.avg(), 0);
assert_eq!(c.peak(), 0);
assert_eq!(c.round(), 0);
assert_eq!(c.total(), 0);
c += 5;
assert_eq!(c.round(), 5);
assert_eq!(c.total(), 5);
c.reset();
assert_eq!(c.avg(), 1);
assert_eq!(c.peak(), 1);
assert_eq!(c.round(), 0);
assert_eq!(c.total(), 5);
c += 10;
assert_eq!(c.round(), 10);
assert_eq!(c.total(), 15);
c.reset();
assert_eq!(c.avg(), 3);
assert_eq!(c.peak(), 3);
assert_eq!(c.round(), 0);
assert_eq!(c.total(), 15);
c += 30;
assert_eq!(c.round(), 30);
assert_eq!(c.total(), 45);
c.reset();
assert_eq!(c.avg(), 8);
assert_eq!(c.peak(), 8);
assert_eq!(c.round(), 0);
assert_eq!(c.total(), 45);
c += 1;
assert_eq!(c.round(), 1);
assert_eq!(c.total(), 46);
c.reset();
assert_eq!(c.avg(), 7);
assert_eq!(c.peak(), 8);
assert_eq!(c.round(), 0);
assert_eq!(c.total(), 46);
}
}