Further simplification of the API

This commit is contained in:
David Peter authored and David Peter committed 2026-10-05 16:00:08 +02:00
1 parent 4badeb6312
commit ebf127338c
4 files changed
+51 -95

No files matched your search

+6 -3
View File
@@ -365,9 +365,12 @@ impl<'a> Benchmark<'a> {
}
// Formatting and console output
let (mean_str, time_unit) = measurements
.time_wall_clock_mean()
.format_auto_with_unit(self.options.time_unit);
let t_wall_clock_mean = measurements.time_wall_clock_mean();
let time_unit = self
.options
.time_unit
.unwrap_or(t_wall_clock_mean.suitable_unit());
let mean_str = t_wall_clock_mean.format_auto(Some(time_unit));
let min_str = measurements.min().format_auto(Some(time_unit));
let max_str = measurements.max().format_auto(Some(time_unit));
let num_str = format!("{num_runs} runs", num_runs = measurements.len());
+3 -7
View File
@@ -53,10 +53,9 @@ pub trait MarkupExporter {
let cmd_str = result.command_with_unused_parameters().replace('|', "\\|");
let mean_str = result
.mean_wall_clock_time()
.format_value_auto(Some(time_unit))
.0;
.format_value_auto(Some(time_unit));
let stddev_str = if let Some(stddev) = result.measurements.stddev() {
format!(" ± {}", stddev.format_value_auto(Some(time_unit)).0)
format!(" ± {}", stddev.format_value_auto(Some(time_unit)))
} else {
"".into()
};
@@ -117,10 +116,7 @@ pub trait MarkupExporter {
fn determine_unit_from_results(results: &[BenchmarkResult]) -> TimeUnit {
if let Some(first_result) = results.first() {
// Use the first BenchmarkResult entry to determine the unit for all entries.
first_result
.mean_wall_clock_time()
.format_auto_with_unit(None)
.1
first_result.mean_wall_clock_time().suitable_unit()
} else {
// Default to `Second`.
TimeUnit::Second
+2 -2
View File
@@ -1,7 +1,7 @@
use std::fmt;
use crate::benchmark::MIN_EXECUTION_TIME;
use crate::quantity::{Time, TimeQuantity, TimeUnit};
use crate::quantity::{Time, TimeQuantity};
pub struct OutlierWarningOptions {
pub warmup_in_use: bool,
@@ -25,7 +25,7 @@ impl fmt::Display for Warnings {
inaccurate because hyperfine can not calibrate the shell startup time much \
more precise than this limit. You can try to use the `-N`/`--shell=none` \
option to disable the shell completely.",
min_execution_time = MIN_EXECUTION_TIME.format_value_in(TimeUnit::MilliSecond, 0)
min_execution_time = MIN_EXECUTION_TIME.format_auto(None)
),
Warnings::NonZeroExitCode => write!(f, "Ignoring non-zero exit code."),
Warnings::SlowInitialRun(time_first_run, ref options) => write!(
+40 -83
View File
@@ -32,10 +32,15 @@ pub trait TimeQuantity {
where
U: si::time::Unit + Conversion<f64, T = f64>;
fn format_value_in(&self, time_unit: TimeUnit, precision: usize) -> String;
fn suitable_unit(&self) -> TimeUnit;
fn format_auto(&self, time_unit: Option<TimeUnit>) -> String;
fn format_auto_with_unit(&self, time_unit: Option<TimeUnit>) -> (String, TimeUnit);
fn format_value_auto(&self, time_unit: Option<TimeUnit>) -> (String, TimeUnit);
fn format_value_auto(&self, time_unit: Option<TimeUnit>) -> String;
}
fn format_value_in(t: Time, u: TimeUnit, precision: Option<usize>) -> String {
let precision = precision.unwrap_or_else(|| if u == TimeUnit::Second { 3 } else { 1 });
u.format(t, precision)
}
impl TimeQuantity for Time {
@@ -46,42 +51,31 @@ impl TimeQuantity for Time {
self.get::<U>()
}
fn format_value_in(&self, u: TimeUnit, precision: usize) -> String {
u.format(*self, precision)
fn suitable_unit(&self) -> TimeUnit {
if *self < Time::new::<millisecond>(1.0) {
TimeUnit::MicroSecond
} else if *self < Time::new::<second>(1.0) {
TimeUnit::MilliSecond
} else {
TimeUnit::Second
}
}
/// Format the given duration as a string. The output-unit can be enforced by setting `unit` to
/// `Some(target_unit)`. If `unit` is `None`, it will be determined automatically.
fn format_auto(&self, time_unit: Option<TimeUnit>) -> String {
self.format_auto_with_unit(time_unit).0
let time_unit = time_unit.unwrap_or_else(|| self.suitable_unit());
let value = format_value_in(*self, time_unit, None);
format!("{} {}", value, time_unit.short_name())
}
/// Like `format_duration`, but returns the target unit as well.
fn format_auto_with_unit(&self, time_unit: Option<TimeUnit>) -> (String, TimeUnit) {
let (out_str, out_unit) = self.format_value_auto(time_unit);
fn format_value_auto(&self, time_unit: Option<TimeUnit>) -> String {
let time_unit = time_unit.unwrap_or_else(|| self.suitable_unit());
(format!("{} {}", out_str, out_unit.short_name()), out_unit)
}
/// Like `format_duration`, but returns the target unit as well.
fn format_value_auto(&self, time_unit: Option<TimeUnit>) -> (String, TimeUnit) {
let (time_unit, precision) = if (*self < Time::new::<millisecond>(1.0)
&& time_unit.is_none())
|| time_unit == Some(TimeUnit::MicroSecond)
{
(TimeUnit::MicroSecond, 1)
} else if (*self < Time::new::<second>(1.0) && time_unit.is_none())
|| time_unit == Some(TimeUnit::MilliSecond)
{
(TimeUnit::MilliSecond, 1)
} else {
let time_unit = time_unit.unwrap_or(TimeUnit::Second);
let precision = if time_unit == TimeUnit::Second { 3 } else { 1 };
(time_unit, precision)
};
(self.format_value_in(time_unit, precision), time_unit)
format_value_in(*self, time_unit, None)
}
}
@@ -211,72 +205,35 @@ fn test_mean() {
}
#[test]
fn test_format_duration() {
let (out_str, out_unit) = Time::new::<second>(1.3).format_auto_with_unit(None);
#[test]
fn test_suitable_unit_information() {
fn test_suiteable_unit() {
assert_eq!(Time::new::<second>(1.3).suitable_unit(), TimeUnit::Second);
assert_eq!(Time::new::<second>(1.0).suitable_unit(), TimeUnit::Second);
assert_eq!(
Information::new::<byte>(512.0).suitable_unit(),
InformationUnit::Byte
Time::new::<second>(0.999).suitable_unit(),
TimeUnit::MilliSecond
);
assert_eq!(
Information::new::<byte>(2048.0).suitable_unit(),
InformationUnit::KibiByte
Time::new::<second>(0.0005).suitable_unit(),
TimeUnit::MicroSecond
);
assert_eq!(
Information::new::<byte>(2_097_152.0).suitable_unit(),
InformationUnit::MebiByte
Time::new::<second>(0.).suitable_unit(),
TimeUnit::MicroSecond
);
assert_eq!(
Information::new::<byte>(2_147_483_648.0).suitable_unit(),
InformationUnit::GibiByte
Time::new::<second>(1000.0).suitable_unit(),
TimeUnit::Second
);
}
let (out_str, out_unit) = Time::new::<second>(1.0).format_auto_with_unit(None);
assert_eq!("1.000 s", out_str);
assert_eq!(TimeUnit::Second, out_unit);
let (out_str, out_unit) = Time::new::<second>(0.999).format_auto_with_unit(None);
assert_eq!("999.0 ms", out_str);
assert_eq!(TimeUnit::MilliSecond, out_unit);
let (out_str, out_unit) = Time::new::<second>(0.0005).format_auto_with_unit(None);
assert_eq!("500.0 µs", out_str);
assert_eq!(TimeUnit::MicroSecond, out_unit);
let (out_str, out_unit) = Time::new::<second>(0.).format_auto_with_unit(None);
assert_eq!("0.0 µs", out_str);
assert_eq!(TimeUnit::MicroSecond, out_unit);
let (out_str, out_unit) = Time::new::<second>(1000.0).format_auto_with_unit(None);
assert_eq!("1000.000 s", out_str);
assert_eq!(TimeUnit::Second, out_unit);
}
#[test]
fn test_format_duration_unit_with_unit() {
let (out_str, out_unit) =
Time::new::<second>(1.3).format_auto_with_unit(Some(TimeUnit::Second));
let out = Time::new::<second>(1.3).format_auto(Some(TimeUnit::Second));
assert_eq!("1.300 s", out);
let out = Time::new::<second>(1.3).format(TimeUnit::MilliSecond);
let out = Time::new::<second>(1.3).format_auto(Some(TimeUnit::MilliSecond));
assert_eq!("1300.0 ms", out);
let (out_str, out_unit) =
Time::new::<second>(1.3).format_auto_with_unit(Some(TimeUnit::MilliSecond));
assert_eq!("1300.0 ms", out_str);
assert_eq!(TimeUnit::MilliSecond, out_unit);
let (out_str, out_unit) =
Time::new::<second>(1.3).format_auto_with_unit(Some(TimeUnit::MicroSecond));
assert_eq!("1300000.0 µs", out_str);
assert_eq!(TimeUnit::MicroSecond, out_unit);
let out = Time::new::<second>(1.3).format_auto(Some(TimeUnit::MicroSecond));
assert_eq!("1300000.0 µs", out);
}