-
Notifications
You must be signed in to change notification settings - Fork 13
Open
Labels
bugSomething isn't workingSomething isn't working
Description
Detail Bug Report
Summary
- Context: The
SlidingThroughput::bps()method calculates throughput (bytes per second) over a sliding time window for network traffic monitoring. - Bug: When
bps()is called with a sub-second duration (e.g.,Duration::from_millis(500)), it returns0.0instead of computing throughput over the closest available window. - Actual vs. expected: The method returns
0.0for anylookbackduration less than 1 second, instead of clamping to the minimum 1-second window and returning the throughput over that period. - Impact: Callers requesting sub-second throughput measurements receive
0.0, which incorrectly suggests zero throughput rather than providing the best available estimate.
Code with bug
pub fn bps(&mut self, lookback: Duration) -> f64 {
let now_tick = self.now_secs();
self.advance_to(now_tick);
let requested_secs = lookback.as_secs();
if requested_secs == 0 { // <-- BUG π΄ Early return prevents clamping
return 0.0;
}
let window_secs = requested_secs.clamp(1, NUM_BUCKETS as u64) as usize;
// Sum last `window_secs` buckets starting from head (inclusive) going backwards
let mut sum: u64 = 0;
let mut idx = self.head_idx;
for _ in 0..window_secs {
sum = sum.saturating_add(self.buckets[idx]);
idx = (idx + self.buckets.len() - 1) % self.buckets.len();
}
sum as f64 / window_secs as f64
}Evidence (Example)
Scenario:
- Record 1000 bytes at t=0
- Request throughput with 500ms lookback
- Request throughput with 1s lookback
Current behavior:
bps(Duration::from_millis(500))returns0.0bps(Duration::from_secs(1))returns1000.0
Expected behavior:
- Both calls should return
1000.0. Sub-second durations truncate to 0 seconds, but the logic should clamp to the minimum 1-second window rather than returning0.0. The early return bypasses the clamping.
Recommended fix
Remove the early return so clamping applies to all durations:
pub fn bps(&mut self, lookback: Duration) -> f64 {
let now_tick = self.now_secs();
self.advance_to(now_tick);
let requested_secs = lookback.as_secs();
// Remove early return; let clamping handle sub-second durations // <-- FIX π’
let window_secs = requested_secs.clamp(1, NUM_BUCKETS as u64) as usize;
// Sum last `window_secs` buckets starting from head (inclusive) going backwards
let mut sum: u64 = 0;
let mut idx = self.head_idx;
for _ in 0..window_secs {
sum = sum.saturating_add(self.buckets[idx]);
idx = (idx + self.buckets.len() - 1) % self.buckets.len();
}
sum as f64 / window_secs as f64
}Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working