mirror of
https://github.com/sharkdp/hyperfine.git
synced 2026-11-02 01:00:31 +00:00
Always compute relative speed comprison for export, closes #642
This commit is contained in:
1 parent
926b8d07c8
commit
9859ecaafe
3 files changed
+62
-38
No files matched your search
@@ -15,43 +15,72 @@ pub fn compare_mean_time(l: &BenchmarkResult, r: &BenchmarkResult) -> Ordering {
|
|||||||
l.mean.partial_cmp(&r.mean).unwrap_or(Ordering::Equal)
|
l.mean.partial_cmp(&r.mean).unwrap_or(Ordering::Equal)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute(results: &[BenchmarkResult]) -> Option<Vec<BenchmarkResultWithRelativeSpeed>> {
|
fn fastest_of(results: &[BenchmarkResult]) -> &BenchmarkResult {
|
||||||
let fastest: &BenchmarkResult = results
|
results
|
||||||
.iter()
|
.iter()
|
||||||
.min_by(|&l, &r| compare_mean_time(l, r))
|
.min_by(|&l, &r| compare_mean_time(l, r))
|
||||||
.expect("at least one benchmark result");
|
.expect("at least one benchmark result")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_relative_speeds<'a>(
|
||||||
|
results: &'a [BenchmarkResult],
|
||||||
|
fastest: &'a BenchmarkResult,
|
||||||
|
) -> Vec<BenchmarkResultWithRelativeSpeed<'a>> {
|
||||||
|
results
|
||||||
|
.iter()
|
||||||
|
.map(|result| {
|
||||||
|
let is_fastest = result == fastest;
|
||||||
|
|
||||||
|
if result.mean == 0.0 {
|
||||||
|
return BenchmarkResultWithRelativeSpeed {
|
||||||
|
result,
|
||||||
|
relative_speed: if is_fastest { 1.0 } else { f64::INFINITY },
|
||||||
|
relative_speed_stddev: None,
|
||||||
|
is_fastest,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let ratio = result.mean / fastest.mean;
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/Propagation_of_uncertainty#Example_formulas
|
||||||
|
// Covariance asssumed to be 0, i.e. variables are assumed to be independent
|
||||||
|
let ratio_stddev = match (result.stddev, fastest.stddev) {
|
||||||
|
(Some(result_stddev), Some(fastest_stddev)) => Some(
|
||||||
|
ratio
|
||||||
|
* ((result_stddev / result.mean).powi(2)
|
||||||
|
+ (fastest_stddev / fastest.mean).powi(2))
|
||||||
|
.sqrt(),
|
||||||
|
),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
BenchmarkResultWithRelativeSpeed {
|
||||||
|
result,
|
||||||
|
relative_speed: ratio,
|
||||||
|
relative_speed_stddev: ratio_stddev,
|
||||||
|
is_fastest,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compute_with_check(
|
||||||
|
results: &[BenchmarkResult],
|
||||||
|
) -> Option<Vec<BenchmarkResultWithRelativeSpeed>> {
|
||||||
|
let fastest = fastest_of(results);
|
||||||
|
|
||||||
if fastest.mean == 0.0 {
|
if fastest.mean == 0.0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(
|
Some(compute_relative_speeds(results, fastest))
|
||||||
results
|
}
|
||||||
.iter()
|
|
||||||
.map(|result| {
|
|
||||||
let ratio = result.mean / fastest.mean;
|
|
||||||
|
|
||||||
// https://en.wikipedia.org/wiki/Propagation_of_uncertainty#Example_formulas
|
/// Same as compute_with_check, potentially resulting in relative speeds of infinity
|
||||||
// Covariance asssumed to be 0, i.e. variables are assumed to be independent
|
pub fn compute(results: &[BenchmarkResult]) -> Vec<BenchmarkResultWithRelativeSpeed> {
|
||||||
let ratio_stddev = match (result.stddev, fastest.stddev) {
|
let fastest = fastest_of(results);
|
||||||
(Some(result_stddev), Some(fastest_stddev)) => Some(
|
|
||||||
ratio
|
|
||||||
* ((result_stddev / result.mean).powi(2)
|
|
||||||
+ (fastest_stddev / fastest.mean).powi(2))
|
|
||||||
.sqrt(),
|
|
||||||
),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
BenchmarkResultWithRelativeSpeed {
|
compute_relative_speeds(results, fastest)
|
||||||
result,
|
|
||||||
relative_speed: ratio,
|
|
||||||
relative_speed_stddev: ratio_stddev,
|
|
||||||
is_fastest: result == fastest,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -83,7 +112,7 @@ fn test_compute_relative_speed() {
|
|||||||
create_result("cmd3", 5.0),
|
create_result("cmd3", 5.0),
|
||||||
];
|
];
|
||||||
|
|
||||||
let annotated_results = compute(&results).unwrap();
|
let annotated_results = compute_with_check(&results).unwrap();
|
||||||
|
|
||||||
assert_relative_eq!(1.5, annotated_results[0].relative_speed);
|
assert_relative_eq!(1.5, annotated_results[0].relative_speed);
|
||||||
assert_relative_eq!(1.0, annotated_results[1].relative_speed);
|
assert_relative_eq!(1.0, annotated_results[1].relative_speed);
|
||||||
@@ -94,7 +123,7 @@ fn test_compute_relative_speed() {
|
|||||||
fn test_compute_relative_speed_for_zero_times() {
|
fn test_compute_relative_speed_for_zero_times() {
|
||||||
let results = vec![create_result("cmd1", 1.0), create_result("cmd2", 0.0)];
|
let results = vec![create_result("cmd1", 1.0), create_result("cmd2", 0.0)];
|
||||||
|
|
||||||
let annotated_results = compute(&results);
|
let annotated_results = compute_with_check(&results);
|
||||||
|
|
||||||
assert!(annotated_results.is_none());
|
assert!(annotated_results.is_none());
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ impl<'a> Scheduler<'a> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut annotated_results) = relative_speed::compute(&self.results) {
|
if let Some(mut annotated_results) = relative_speed::compute_with_check(&self.results) {
|
||||||
annotated_results.sort_by(|l, r| relative_speed::compare_mean_time(l.result, r.result));
|
annotated_results.sort_by(|l, r| relative_speed::compare_mean_time(l.result, r.result));
|
||||||
|
|
||||||
let fastest = &annotated_results[0];
|
let fastest = &annotated_results[0];
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::output::format::format_duration_value;
|
|||||||
use crate::util::units::Unit;
|
use crate::util::units::Unit;
|
||||||
|
|
||||||
use super::Exporter;
|
use super::Exporter;
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::Result;
|
||||||
|
|
||||||
pub enum Alignment {
|
pub enum Alignment {
|
||||||
Left,
|
Left,
|
||||||
@@ -106,13 +106,8 @@ impl<T: MarkupExporter> Exporter for T {
|
|||||||
fn serialize(&self, results: &[BenchmarkResult], unit: Option<Unit>) -> Result<Vec<u8>> {
|
fn serialize(&self, results: &[BenchmarkResult], unit: Option<Unit>) -> Result<Vec<u8>> {
|
||||||
let unit = unit.unwrap_or_else(|| determine_unit_from_results(results));
|
let unit = unit.unwrap_or_else(|| determine_unit_from_results(results));
|
||||||
let entries = relative_speed::compute(results);
|
let entries = relative_speed::compute(results);
|
||||||
if entries.is_none() {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"Relative speed comparison is not available for markup exporter."
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let table = self.table_results(&entries.unwrap(), unit);
|
let table = self.table_results(&entries, unit);
|
||||||
Ok(table.as_bytes().to_vec())
|
Ok(table.as_bytes().to_vec())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user