Simplify parameterized reference handling

This commit is contained in:
David Peter committed 2026-10-05 15:07:46 +02:00
1 parent f7429e2fb2
commit 463a889638
8 files changed
+210 -693

No files matched your search

+22 -52
View File
@@ -16,6 +16,20 @@ pub struct BenchmarkResultWithRelativeSpeed<'a> {
pub relative_ordering: Ordering,
}
impl BenchmarkResultWithRelativeSpeed<'_> {
pub fn reference_label(&self) -> &'static str {
if self.is_reference {
" (reference)"
} else {
match self.relative_ordering {
Ordering::Less => " (faster)",
Ordering::Equal => " (same speed)",
Ordering::Greater => " (slower)",
}
}
}
}
pub fn compare_mean_time(l: &BenchmarkResult, r: &BenchmarkResult) -> Ordering {
l.mean_wall_clock_time()
.partial_cmp(&r.mean_wall_clock_time())
@@ -29,7 +43,7 @@ pub fn fastest_of(results: &[BenchmarkResult]) -> &BenchmarkResult {
.expect("at least one benchmark result")
}
pub fn compute_relative_speeds<'a>(
fn compute_relative_speeds<'a>(
results: &'a [BenchmarkResult],
reference: &'a BenchmarkResult,
sort_order: SortOrder,
@@ -125,14 +139,14 @@ pub fn compute_with_check(
Some(compute_relative_speeds(results, fastest, sort_order))
}
/// Same as compute_with_check, potentially resulting in relative speeds of infinity
pub fn compute(
results: &[BenchmarkResult],
/// Compute relative speeds against the given reference, or the fastest result.
pub fn compute<'a>(
results: &'a [BenchmarkResult],
sort_order: SortOrder,
) -> Vec<BenchmarkResultWithRelativeSpeed<'_>> {
let fastest = fastest_of(results);
compute_relative_speeds(results, fastest, sort_order)
reference: Option<&'a BenchmarkResult>,
) -> Vec<BenchmarkResultWithRelativeSpeed<'a>> {
let reference = reference.unwrap_or_else(|| fastest_of(results));
compute_relative_speeds(results, reference, sort_order)
}
#[cfg(test)]
@@ -205,25 +219,6 @@ fn reference_identity_distinguishes_equal_results() {
assert!(!entries[1].is_reference);
}
#[test]
fn reference_ratios_indicate_faster_and_slower_runs() {
use approx::assert_relative_eq;
let results = vec![
create_result("faster", 1.0),
create_result("reference", 2.0),
create_result("slower", 3.0),
];
let entries = compute_relative_speeds(&results, &results[1], SortOrder::Command);
assert_relative_eq!(entries[0].relative_speed, 2.0);
assert_relative_eq!(entries[1].relative_speed, 1.0);
assert_relative_eq!(entries[2].relative_speed, 1.5);
assert!(!entries[0].is_reference);
assert!(entries[1].is_reference);
assert!(!entries[2].is_reference);
}
#[test]
fn reference_ratios_handle_zero_times() {
let mut results = vec![create_result("reference", 2.0), create_result("zero", 0.0)];
@@ -239,28 +234,3 @@ fn reference_ratios_handle_zero_times() {
assert_eq!(entries[0].relative_speed_stddev, None);
assert_eq!(entries[1].relative_speed, 1.0);
}
#[test]
fn reference_ratio_propagates_uncertainty() {
use crate::benchmark::measurement::Measurement;
use crate::quantity::second;
use approx::assert_relative_eq;
let mut results = vec![
create_result("faster", 1.0),
create_result("reference", 3.0),
];
for (result, times) in results.iter_mut().zip([[1.0, 2.0, 3.0], [3.0, 4.0, 5.0]]) {
result.measurements.measurements = times
.iter()
.copied()
.map(|seconds| Measurement {
time_wall_clock: Time::new::<second>(seconds),
..Default::default()
})
.collect();
}
let entries = compute_relative_speeds(&results, &results[1], SortOrder::Command);
assert_relative_eq!(entries[0].relative_speed, 2.0);
assert_relative_eq!(entries[0].relative_speed_stddev.unwrap(), 1.118033988749895);
}
+7 -20
View File
@@ -44,7 +44,6 @@ impl<'a> Scheduler<'a> {
.options
.reference_command
.as_ref()
.filter(|_| !self.options.parameterized_mode)
.map(|cmd| Command::new(self.options.reference_name.as_deref(), cmd));
executor.calibrate()?;
@@ -56,7 +55,7 @@ impl<'a> Scheduler<'a> {
// We export results after each individual benchmark, because
// we would risk losing them if a later benchmark fails.
self.export_manager
.write_results(&self.results, true, self.reference_index())?;
.write_results(&self.results, true, self.options.reference_index)?;
}
Ok(())
@@ -72,7 +71,8 @@ impl<'a> Scheduler<'a> {
}
let reference = self
.reference_index()
.options
.reference_index
.map(|index| &self.results[index])
.unwrap_or_else(|| relative_speed::fastest_of(&self.results));
@@ -130,16 +130,10 @@ impl<'a> Scheduler<'a> {
console_writeln!(stdout, "{}", "Relative speed comparison".bold())?;
for item in annotated_results {
let relationship = if self.reference_index().is_none() {
""
} else if item.is_reference {
" (reference)"
let relationship = if self.options.reference_index.is_some() {
item.reference_label()
} else {
match item.relative_ordering {
Ordering::Less => " (faster)",
Ordering::Equal => " (same speed)",
Ordering::Greater => " (slower)",
}
""
};
console_writeln!(
stdout,
@@ -174,16 +168,9 @@ impl<'a> Scheduler<'a> {
Ok(())
}
fn reference_index(&self) -> Option<usize> {
self.options
.reference_command
.as_ref()
.map(|_| self.options.parameterized_reference_index.unwrap_or(0))
}
pub fn final_export(&self) -> Result<()> {
self.export_manager
.write_results(&self.results, false, self.reference_index())
.write_results(&self.results, false, self.options.reference_index)
}
}