diff --git a/runtime/src/bucket_map_holder_stats.rs b/runtime/src/bucket_map_holder_stats.rs index 26662fcd69..08df6c2f02 100644 --- a/runtime/src/bucket_map_holder_stats.rs +++ b/runtime/src/bucket_map_holder_stats.rs @@ -38,16 +38,19 @@ pub struct BucketMapHolderStats { pub active_threads: AtomicU64, pub get_range_us: AtomicU64, last_age: AtomicU8, + last_ages_flushed: AtomicU64, pub flush_scan_update_us: AtomicU64, pub flush_remove_us: AtomicU64, pub flush_grow_us: AtomicU64, last_was_startup: AtomicBool, last_time: AtomicInterval, + bins: u64, } impl BucketMapHolderStats { pub fn new(bins: usize) -> BucketMapHolderStats { BucketMapHolderStats { + bins: bins as u64, per_bucket_count: (0..bins) .into_iter() .map(|_| AtomicU64::default()) @@ -82,17 +85,23 @@ impl BucketMapHolderStats { } fn ms_per_age(&self, storage: &BucketMapHolder, elapsed_ms: u64) -> u64 { - if !storage.get_startup() { - let age_now = storage.current_age(); - let last_age = self.last_age.swap(age_now, Ordering::Relaxed) as u64; - let mut age_now = age_now as u64; - if last_age > age_now { - // age wrapped - age_now += u8::MAX as u64 + 1; - } - let age_delta = age_now.saturating_sub(last_age) as u64; - if age_delta > 0 { - return elapsed_ms / age_delta; + let age_now = storage.current_age(); + let ages_flushed = storage.count_ages_flushed() as u64; + let last_age = self.last_age.swap(age_now, Ordering::Relaxed) as u64; + let last_ages_flushed = self.last_ages_flushed.swap(ages_flushed, Ordering::Relaxed) as u64; + let mut age_now = age_now as u64; + if last_age > age_now { + // age wrapped + age_now += u8::MAX as u64 + 1; + } + let age_delta = age_now.saturating_sub(last_age) as u64; + if age_delta > 0 { + return elapsed_ms / age_delta; + } else { + // did not advance an age, but probably did partial work, so report that + let bin_delta = ages_flushed.saturating_sub(last_ages_flushed); + if bin_delta > 0 { + return elapsed_ms * self.bins / bin_delta; } } 0 // avoid crazy numbers