in core/bench/src/analytics/time_series/calculators/throughput.rs [77:142]
fn calculate(&self, records: &[BenchmarkRecord], bucket_size: IggyDuration) -> TimeSeries {
if records.len() < 2 {
return TimeSeries {
points: Vec::new(),
kind: self.calculator.kind(),
};
}
let bucket_size_us = bucket_size.as_micros();
let max_time_us = records.iter().map(|r| r.elapsed_time_us).max().unwrap_or(0);
let num_buckets = max_time_us.div_ceil(bucket_size_us);
let mut values_per_bucket = vec![0u64; num_buckets as usize];
for window in records.windows(2) {
let (prev, current) = (&window[0], &window[1]);
let delta_time_us = current.elapsed_time_us.saturating_sub(prev.elapsed_time_us);
if delta_time_us == 0 {
continue;
}
let delta_value = self.calculator.get_delta_value(current, prev);
let value_per_us = delta_value as f64 / delta_time_us as f64;
let mut remaining_time_us = delta_time_us;
let mut current_time_us = prev.elapsed_time_us;
while remaining_time_us > 0 {
let bucket_index = current_time_us / bucket_size_us;
if bucket_index >= num_buckets {
break;
}
let bucket_start_us = bucket_index * bucket_size_us;
let bucket_end_us = bucket_start_us + bucket_size_us;
let overlap_start_us = current_time_us.max(bucket_start_us);
let overlap_end_us = (current_time_us + remaining_time_us).min(bucket_end_us);
let overlap_us = overlap_end_us.saturating_sub(overlap_start_us);
if overlap_us > 0 {
let allocated_value = (value_per_us * overlap_us as f64).round() as u64;
values_per_bucket[bucket_index as usize] += allocated_value;
}
let allocated_time_us = overlap_end_us.saturating_sub(current_time_us);
remaining_time_us = remaining_time_us.saturating_sub(allocated_time_us);
current_time_us = overlap_end_us;
}
}
let points = values_per_bucket
.iter()
.enumerate()
.filter(|(_, &value)| value > 0)
.map(|(i, &value)| {
let time_s = (i as u64 * bucket_size_us) as f64 / 1_000_000.0;
let throughput = self.calculator.calculate_throughput(value, bucket_size_us);
let rounded_throughput = (throughput * 1000.0).round() / 1000.0;
TimePoint::new(time_s, rounded_throughput)
})
.collect();
TimeSeries {
points,
kind: self.calculator.kind(),
}
}