diff --git a/src/state.rs b/src/state.rs index 72bcd426..171b4855 100644 --- a/src/state.rs +++ b/src/state.rs @@ -370,7 +370,8 @@ impl TabExpandedString { /// Ring buffer with constant capacity. Used by `ProgressBar`s to display `{eta}`, /// `{eta_precise}`, and `{*_per_sec}`. pub(crate) struct Estimator { - steps: [f64; 16], + steps: [u64; 16], + step_durations: [f64; 16], pos: u8, full: bool, prev: (u64, Instant), @@ -379,7 +380,8 @@ pub(crate) struct Estimator { impl Estimator { fn new(now: Instant) -> Self { Self { - steps: [0.0; 16], + steps: [0; 16], + step_durations: [0.0; 16], pos: 0, full: false, prev: (0, now), @@ -388,7 +390,9 @@ impl Estimator { fn record(&mut self, new: u64, now: Instant) { let delta = new.saturating_sub(self.prev.0); - if delta == 0 || now < self.prev.1 { + let elapsed = duration_to_secs(now - self.prev.1); + + if delta == 0 || elapsed < 0.0 { // Reset on backwards seek to prevent breakage from seeking to the end for length determination // See https://github.com/console-rs/indicatif/issues/480 if new < self.prev.0 { @@ -397,14 +401,9 @@ impl Estimator { return; } - let elapsed = now - self.prev.1; - let divisor = delta as f64; - let mut batch = 0.0; - if divisor != 0.0 { - batch = duration_to_secs(elapsed) / divisor; - }; + self.steps[self.pos as usize] = delta; + self.step_durations[self.pos as usize] = elapsed; - self.steps[self.pos as usize] = batch; self.pos = (self.pos + 1) % 16; if !self.full && self.pos == 0 { self.full = true; @@ -422,7 +421,9 @@ impl Estimator { /// Average time per step in seconds, using rolling buffer of last 15 steps fn seconds_per_step(&self) -> f64 { let len = self.len(); - self.steps[0..len].iter().sum::() / len as f64 + let total_steps = self.steps[0..len].iter().sum::(); + let total_duration = self.step_durations[0..len].iter().sum::(); + total_duration / total_steps as f64 } fn len(&self) -> usize {