bitfold_host/
throughput.rs

1use std::{
2    fmt::{self, Debug, Display},
3    time::{Duration, Instant},
4};
5
6/// Helper to monitor throughput over fixed windows.
7pub struct ThroughputMonitoring {
8    throughput_duration: Duration,
9    timer: Instant,
10    current_throughput: u32,
11    measured_throughput: Vec<ThroughputEntry>,
12}
13
14#[derive(Debug)]
15struct ThroughputEntry {
16    measured_throughput: u32,
17    _start: Instant,
18}
19
20impl ThroughputEntry {
21    fn new(measured_throughput: u32, time: Instant) -> ThroughputEntry {
22        ThroughputEntry { measured_throughput, _start: time }
23    }
24}
25
26impl ThroughputMonitoring {
27    /// Creates a new throughput monitor with the specified window duration.
28    pub fn new(throughput_duration: Duration) -> ThroughputMonitoring {
29        ThroughputMonitoring {
30            throughput_duration,
31            timer: Instant::now(),
32            current_throughput: 0,
33            measured_throughput: Vec::new(),
34        }
35    }
36
37    /// Records a tick and returns true if a measurement window completed.
38    pub fn tick(&mut self) -> bool {
39        if self.timer.elapsed() >= self.throughput_duration {
40            self.measured_throughput
41                .push(ThroughputEntry::new(self.current_throughput, self.timer));
42            self.current_throughput = 0;
43            self.timer = Instant::now();
44            true
45        } else {
46            self.current_throughput += 1;
47            false
48        }
49    }
50
51    /// Returns the average throughput across all measurement windows.
52    pub fn average(&self) -> u32 {
53        if !self.measured_throughput.is_empty() {
54            return self.measured_throughput.iter().map(|x| x.measured_throughput).sum::<u32>()
55                / self.measured_throughput.len() as u32;
56        }
57        0
58    }
59
60    /// Resets all throughput measurements.
61    pub fn reset(&mut self) {
62        self.current_throughput = 0;
63        self.measured_throughput.clear();
64    }
65
66    /// Returns the throughput from the most recent completed window.
67    pub fn last_throughput(&self) -> u32 {
68        self.measured_throughput.last().map(|x| x.measured_throughput).unwrap_or(0)
69    }
70
71    /// Returns the total number of ticks measured across all windows.
72    pub fn total_measured_ticks(&self) -> u32 {
73        self.measured_throughput.iter().map(|x| x.measured_throughput).sum::<u32>()
74            + self.current_throughput
75    }
76}
77
78impl Debug for ThroughputMonitoring {
79    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
80        write!(
81            f,
82            "Current Throughput: {}, Elapsed Time: {:#?}, Average Throughput: {}",
83            self.last_throughput(),
84            self.timer.elapsed(),
85            self.average()
86        )
87    }
88}
89
90impl Display for ThroughputMonitoring {
91    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
92        write!(
93            f,
94            "Current Throughput: {}, Elapsed Time: {:#?}, Average Throughput: {}",
95            self.last_throughput(),
96            self.timer.elapsed(),
97            self.average()
98        )
99    }
100}