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

+17 -26
View File
@@ -67,28 +67,19 @@ pub trait MarkupExporter {
&& !entry.is_reference
&& entry.relative_ordering == Ordering::Equal
&& measurement.mean_wall_clock_time() == Time::zero());
let rel_str = if relative_unavailable {
let relative = if relative_unavailable {
"N/A".to_string()
} else {
format!("{:.2}", entry.relative_speed)
};
let rel_stddev_str = if relative_unavailable || entry.is_reference {
"".into()
} else if let Some(stddev) = entry.relative_speed_stddev {
format!(" ± {stddev:.2}")
} else {
"".into()
};
let rel_direction = if relative_unavailable || !explicit_reference {
""
} else if entry.is_reference {
" (reference)"
} else {
match entry.relative_ordering {
Ordering::Less => " (faster)",
Ordering::Greater => " (slower)",
Ordering::Equal => " (same speed)",
}
let stddev = match (entry.is_reference, entry.relative_speed_stddev) {
(false, Some(stddev)) => format!(" ± {stddev:.2}"),
_ => String::new(),
};
let label = if explicit_reference {
entry.reference_label()
} else {
""
};
format!("{:.2}{stddev}{label}", entry.relative_speed)
};
// prepare table row entries
@@ -97,7 +88,7 @@ pub trait MarkupExporter {
&format!("{mean_str}{stddev_str}"),
&min_str,
&max_str,
&format!("{rel_str}{rel_stddev_str}{rel_direction}"),
&relative,
]))
}
@@ -144,11 +135,11 @@ impl<T: MarkupExporter> Exporter for T {
// Do not report ratios against another benchmark while the selected
// reference is still pending in an intermediate export.
let reference_pending = reference_index.is_some_and(|i| i >= results.len());
let entries = if let Some(reference) = reference_index.and_then(|i| results.get(i)) {
relative_speed::compute_relative_speeds(results, reference, sort_order)
} else {
relative_speed::compute(results, sort_order)
};
let entries = relative_speed::compute(
results,
sort_order,
reference_index.and_then(|i| results.get(i)),
);
let table =
self.table_results(&entries, unit, reference_pending, reference_index.is_some());
+1 -166
View File
@@ -12,174 +12,9 @@ fn get_output<E: Exporter + Default>(
results: &[BenchmarkResult],
unit: Option<TimeUnit>,
sort_order: SortOrder,
) -> String {
get_output_with_reference::<E>(results, unit, sort_order, None)
}
fn get_output_with_reference<E: Exporter + Default>(
results: &[BenchmarkResult],
unit: Option<TimeUnit>,
sort_order: SortOrder,
reference_index: Option<usize>,
) -> String {
let exporter = E::default();
String::from_utf8(
exporter
.serialize(results, unit, sort_order, reference_index)
.unwrap(),
)
.unwrap()
}
#[test]
fn test_markup_exports_identify_explicit_reference_and_direction() {
let benchmark = |name: &str, seconds| {
let measurement = Measurement {
time_wall_clock: Time::new::<second>(seconds),
..Measurement::default()
};
BenchmarkResult {
command: name.to_owned(),
command_with_unused_parameters: name.to_owned(),
measurements: Measurements::new(vec![measurement, measurement]),
..BenchmarkResult::default()
}
};
let results = [
benchmark("faster", 1.0),
benchmark("reference", 2.0),
benchmark("equal", 2.0),
benchmark("slower", 3.0),
];
for sort_order in [SortOrder::Command, SortOrder::MeanTime] {
let outputs = [
get_output_with_reference::<MarkdownExporter>(
&results,
Some(TimeUnit::Second),
sort_order,
Some(1),
),
get_output_with_reference::<AsciidocExporter>(
&results,
Some(TimeUnit::Second),
sort_order,
Some(1),
),
get_output_with_reference::<OrgmodeExporter>(
&results,
Some(TimeUnit::Second),
sort_order,
Some(1),
),
];
for output in outputs {
for expected in [
"2.00 ± 0.00 (faster)",
"1.00 (reference)",
"1.00 ± 0.00 (same speed)",
"1.50 ± 0.00 (slower)",
] {
assert!(output.contains(expected), "{}", output);
}
}
}
}
#[test]
fn test_markup_exports_leave_pending_reference_ratios_unavailable() {
let results = [BenchmarkResult {
command: "sleep 1".into(),
command_with_unused_parameters: "sleep 1".into(),
measurements: Measurements::new(vec![Measurement {
time_wall_clock: Time::new::<second>(1.0),
..Measurement::default()
}]),
..BenchmarkResult::default()
}];
for sort_order in [SortOrder::Command, SortOrder::MeanTime] {
let outputs = [
get_output_with_reference::<MarkdownExporter>(
&results,
Some(TimeUnit::Second),
sort_order,
Some(1),
),
get_output_with_reference::<AsciidocExporter>(
&results,
Some(TimeUnit::Second),
sort_order,
Some(1),
),
get_output_with_reference::<OrgmodeExporter>(
&results,
Some(TimeUnit::Second),
sort_order,
Some(1),
),
];
for output in outputs {
assert!(output.contains("N/A"), "{}", output);
assert!(!output.contains("(reference)"), "{}", output);
}
}
}
#[test]
fn test_markup_exports_with_zero_reference() {
let benchmark = |name: &str, seconds| BenchmarkResult {
command: name.to_owned(),
command_with_unused_parameters: name.to_owned(),
measurements: Measurements::new(vec![Measurement {
time_wall_clock: Time::new::<second>(seconds),
..Measurement::default()
}]),
..BenchmarkResult::default()
};
let results = [
benchmark("other zero", 0.0),
benchmark("reference", 0.0),
benchmark("slower", 1.0),
];
for sort_order in [SortOrder::Command, SortOrder::MeanTime] {
for reference in [Some(1), Some(3), None] {
let outputs = [
get_output_with_reference::<MarkdownExporter>(
&results,
Some(TimeUnit::Second),
sort_order,
reference,
),
get_output_with_reference::<AsciidocExporter>(
&results,
Some(TimeUnit::Second),
sort_order,
reference,
),
get_output_with_reference::<OrgmodeExporter>(
&results,
Some(TimeUnit::Second),
sort_order,
reference,
),
];
for output in outputs {
match reference {
Some(1) => {
assert_eq!(output.matches("N/A").count(), 1, "{}", output);
assert!(output.contains("1.00 (reference)"), "{}", output);
assert!(output.contains("inf (slower)"), "{}", output);
}
Some(_) => assert_eq!(output.matches("N/A").count(), 3, "{}", output),
None => {
assert!(!output.contains("N/A"), "{}", output);
assert!(output.contains("inf"), "{}", output);
assert!(!output.contains("(reference)"), "{}", output);
}
}
}
}
}
String::from_utf8(exporter.serialize(results, unit, sort_order, None).unwrap()).unwrap()
}
/// Ensure the makrup output includes the table header and the multiple