fluxbench_cli/executor/statistics.rs
1//! Statistics Computation
2//!
3//! Parallel computation of summary statistics for benchmark results.
4//!
5//! Uses Rayon to parallelize statistics computation across benchmarks.
6//! Each benchmark's samples are processed independently to compute:
7//! - Central tendency (mean, median)
8//! - Dispersion (std dev, min, max)
9//! - Percentiles (p50, p90, p95, p99, p999)
10//! - Outlier detection via IQR method
11
12use super::execution::{BenchExecutionResult, ExecutionConfig};
13use fluxbench_stats::{OutlierMethod, SummaryStatistics, compute_summary};
14use rayon::prelude::*;
15
16/// Compute statistics for benchmark results (parallelized with Rayon)
17///
18/// Uses Rayon for parallel computation of summary statistics across all benchmarks.
19/// Each benchmark's samples are independently processed, making this highly parallelizable.
20///
21/// # Arguments
22/// * `results` - Benchmark execution results containing samples
23/// * `_config` - Execution configuration. Currently unused but reserved for future
24/// extensions such as configurable outlier detection methods, custom percentile
25/// thresholds, or alternative statistical algorithms.
26///
27/// # Returns
28/// Vector of (benchmark_id, optional statistics) pairs. Returns `None` for benchmarks
29/// with no samples (e.g., crashed or skipped benchmarks).
30pub fn compute_statistics(
31 results: &[BenchExecutionResult],
32 _config: &ExecutionConfig,
33) -> Vec<(String, Option<SummaryStatistics>)> {
34 results
35 .par_iter() // Parallel iteration
36 .map(|r| {
37 if r.samples.is_empty() {
38 (r.benchmark_id.clone(), None)
39 } else {
40 let stats = compute_summary(&r.samples, OutlierMethod::Iqr { k: 3 }); // k=3 means 1.5*IQR
41 (r.benchmark_id.clone(), Some(stats))
42 }
43 })
44 .collect()
45}