Skip to content

Commit

Permalink
more precise throughput computation
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Aug 10, 2020
1 parent 52661ee commit 360d3ee
Showing 1 changed file with 26 additions and 7 deletions.
33 changes: 26 additions & 7 deletions src/throughput.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{progress, unit};
use std::collections::VecDeque;
use std::time::{Duration, SystemTime};

const THROTTLE_INTERVAL: Duration = Duration::from_secs(1);
Expand All @@ -7,8 +8,8 @@ const ONCE_A_SECOND: Duration = Duration::from_secs(1);
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
struct State {
observed: Duration,
aggregate_value_for_observed_duration: progress::Step,
last_value: progress::Step,
elapsed_values: VecDeque<(Duration, progress::Step)>,

last_update_duration: Duration,
precomputed_throughput: Option<progress::Step>,
Expand All @@ -18,22 +19,40 @@ impl State {
fn new(value: progress::Step, elapsed: Duration) -> Self {
State {
observed: elapsed,
aggregate_value_for_observed_duration: value,
last_value: value,
last_update_duration: elapsed,
elapsed_values: {
let mut v = VecDeque::with_capacity(6); // default frames per second
v.push_back((elapsed, value));
v
},

last_update_duration: elapsed,
precomputed_throughput: None,
}
}

fn compute_throughput(&self) -> progress::Step {
((self.aggregate_value_for_observed_duration as f64 / self.observed.as_secs_f64())
* ONCE_A_SECOND.as_secs_f64()) as progress::Step
fn compute_throughput(&mut self) -> progress::Step {
let mut observed: Duration = self.elapsed_values.iter().map(|e| e.0).sum();
while !self.elapsed_values.is_empty() && observed > ONCE_A_SECOND {
let candidate = self
.elapsed_values
.front()
.map(|e| e.0)
.expect("at least one item as we are in the checked loop");
if observed.checked_sub(candidate).unwrap_or_default() <= ONCE_A_SECOND {
break;
}
observed -= candidate;
self.elapsed_values.pop_front();
}
let observed_value: progress::Step = self.elapsed_values.iter().map(|e| e.1).sum();
((observed_value as f64 / observed.as_secs_f64()) * ONCE_A_SECOND.as_secs_f64()) as progress::Step
}

fn update(&mut self, value: progress::Step, elapsed: Duration) -> Option<unit::display::Throughput> {
self.aggregate_value_for_observed_duration += value.saturating_sub(self.last_value);
self.observed += elapsed;
self.elapsed_values
.push_back((elapsed, value.saturating_sub(self.last_value)));
self.last_value = value;
if self.observed - self.last_update_duration > THROTTLE_INTERVAL {
self.precomputed_throughput = Some(self.compute_throughput());
Expand Down

0 comments on commit 360d3ee

Please sign in to comment.