This commit is contained in:
David Peter authored and David Peter committed 2026-10-05 15:59:10 +02:00
1 parent 9ec7a9c920
commit 641451aea6
15 files changed
+459 -443

No files matched your search

Generated
+87 -9
View File
@@ -396,7 +396,7 @@ dependencies = [
"tempfile",
"thiserror",
"uom",
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
@@ -505,6 +505,83 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
[[package]]
name = "num"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational 0.2.4",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
dependencies = [
"autocfg 1.4.0",
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
dependencies = [
"autocfg 1.4.0",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [
"autocfg 1.4.0",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
dependencies = [
"autocfg 1.4.0",
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
dependencies = [
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.19"
@@ -926,8 +1003,14 @@ dependencies = [
]
[[package]]
name = "toml_parser"
version = "1.1.3+spec-1.1.0"
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56"
dependencies = [
@@ -952,18 +1035,13 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "unicode-width"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
[[package]]
name = "uom"
version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffd36e5350a65d112584053ee91843955826bf9e56ec0d1351214e01f6d7cd9c"
dependencies = [
"num-rational 0.4.2",
"num-traits",
"typenum",
]
+6
View File
@@ -28,6 +28,12 @@ rand = "0.10"
shell-words = "1.1"
thiserror = "2.0"
anyhow = "1.0"
uom = { version = "0.36.0", default-features = false, features = [
"std",
"si",
"f64",
"u64",
] }
[target.'cfg(not(windows))'.dependencies]
libc = "0.2"
+2 -2
View File
@@ -2,7 +2,7 @@ use std::collections::BTreeMap;
use serde::Serialize;
use crate::benchmark::{measurement::Measurements, quantity::Second};
use crate::benchmark::{measurement::Measurements, quantity::Time};
/// Parameter value and whether it was used in the command line template
#[derive(Debug, Default, Clone, Serialize, PartialEq)]
@@ -37,7 +37,7 @@ pub struct BenchmarkResult {
impl BenchmarkResult {
/// The average wall clock time
pub fn mean_wall_clock_time(&self) -> Second {
pub fn mean_wall_clock_time(&self) -> Time {
self.measurements.time_wall_clock_mean()
}
+18 -14
View File
@@ -4,8 +4,9 @@ use std::process::ExitStatus;
use crate::benchmark::measurement::Measurement;
use crate::benchmark::measurement::Measurements;
use crate::benchmark::quantity::Byte;
use crate::benchmark::quantity::Second;
use crate::benchmark::quantity::Information;
use crate::benchmark::quantity::InformationQuantity;
use crate::benchmark::quantity::{Time, TimeQuantity};
use crate::command::Command;
use crate::options::{
CmdFailureAction, CommandInputPolicy, CommandOutputPolicy, Options, OutputStyleOption, Shell,
@@ -172,8 +173,8 @@ impl Executor for RawExecutor<'_> {
Ok(())
}
fn time_overhead(&self) -> Second {
Second::zero()
fn time_overhead(&self) -> Time {
Time::zero()
}
}
@@ -223,9 +224,9 @@ impl Executor for ShellExecutor<'_> {
)?;
// Subtract shell spawning time
fn ensure_non_negative(time: Second) -> Second {
if time < Second::zero() {
Second::zero()
fn ensure_non_negative(time: Time) -> Time {
if time < Time::zero() {
Time::zero()
} else {
time
}
@@ -310,7 +311,7 @@ impl Executor for ShellExecutor<'_> {
Ok(())
}
fn time_overhead(&self) -> Second {
fn time_overhead(&self) -> Time {
self.shell_spawning_time.as_ref().unwrap().time_wall_clock
}
}
@@ -327,7 +328,7 @@ impl MockExecutor {
fn extract_time<S: AsRef<str>>(sleep_command: S) -> Time {
assert!(sleep_command.as_ref().starts_with("sleep "));
Second::new(
Time::from_seconds(
sleep_command
.as_ref()
.trim_start_matches("sleep ")
@@ -359,9 +360,9 @@ impl Executor for MockExecutor {
Ok(Measurement {
time_wall_clock: Self::extract_time(command.get_command_line()),
time_user: Second::zero(),
time_system: Second::zero(),
peak_memory_usage: Byte::new(0),
time_user: Time::zero(),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(0),
exit_status,
})
}
@@ -372,7 +373,7 @@ impl Executor for MockExecutor {
fn time_overhead(&self) -> Time {
match &self.shell {
None => Second::zero(),
None => Time::zero(),
Some(shell) => Self::extract_time(shell),
}
}
@@ -380,5 +381,8 @@ impl Executor for MockExecutor {
#[test]
fn test_mock_executor_extract_time() {
assert_eq!(MockExecutor::extract_time("sleep 0.1"), Second::new(0.1));
assert_eq!(
MockExecutor::extract_time("sleep 0.1"),
Time::from_seconds(0.1)
);
}
+22 -15
View File
@@ -2,7 +2,10 @@ use std::process::ExitStatus;
use serde::Serialize;
use crate::benchmark::quantity::{max, mean, median, min, standard_deviation, Byte, Second};
use crate::benchmark::quantity::{
max, mean, median, min, second, serialize_information, serialize_time, standard_deviation,
Information, Time, TimeQuantity,
};
use crate::outlier_detection::modified_zscores;
use crate::util::exit_code::extract_exit_code;
@@ -20,16 +23,20 @@ where
#[derive(Debug, Clone, Default, Serialize, PartialEq)]
pub struct Measurement {
/// Elapsed wall clock time (real time)
pub time_wall_clock: Second,
#[serde(serialize_with = "serialize_time")]
pub time_wall_clock: Time,
/// Time spent in user mode
pub time_user: Second,
#[serde(serialize_with = "serialize_time")]
pub time_user: Time,
/// Time spent in kernel mode
pub time_system: Second,
#[serde(serialize_with = "serialize_time")]
pub time_system: Time,
/// Maximum memory usage of the process
pub peak_memory_usage: Byte,
#[serde(serialize_with = "serialize_information")]
pub peak_memory_usage: Information,
// The exit status of the process
#[serde(rename = "exit_code", serialize_with = "serialize_exit_status")]
@@ -58,7 +65,7 @@ impl Measurements {
self.measurements.push(measurement);
}
pub fn wall_clock_times(&self) -> Vec<Second> {
pub fn wall_clock_times(&self) -> Vec<Time> {
self.measurements
.iter()
.map(|m| m.time_wall_clock)
@@ -66,12 +73,12 @@ impl Measurements {
}
/// The average wall clock time
pub fn time_wall_clock_mean(&self) -> Second {
pub fn time_wall_clock_mean(&self) -> Time {
mean(&self.wall_clock_times())
}
/// The standard deviation of all wall clock times. Not available if only one run has been performed
pub fn stddev(&self) -> Option<Second> {
pub fn stddev(&self) -> Option<Time> {
let times = self.wall_clock_times();
if times.len() < 2 {
@@ -82,22 +89,22 @@ impl Measurements {
}
/// The median wall clock time
pub fn median(&self) -> Second {
pub fn median(&self) -> Time {
median(&self.wall_clock_times())
}
/// The minimum wall clock time
pub fn min(&self) -> Second {
pub fn min(&self) -> Time {
min(&self.wall_clock_times())
}
/// The maximum wall clock time
pub fn max(&self) -> Second {
pub fn max(&self) -> Time {
max(&self.wall_clock_times())
}
/// The average user time
pub fn time_user_mean(&self) -> Second {
pub fn time_user_mean(&self) -> Time {
mean(
&self
.measurements
@@ -108,7 +115,7 @@ impl Measurements {
}
/// The average system time
pub fn time_system_mean(&self) -> Second {
pub fn time_system_mean(&self) -> Time {
mean(
&self
.measurements
@@ -118,7 +125,7 @@ impl Measurements {
)
}
pub fn peak_memory_usage_mean(&self) -> Byte {
pub fn peak_memory_usage_mean(&self) -> Information {
self.measurements
.iter()
.map(|m| m.peak_memory_usage)
@@ -131,7 +138,7 @@ impl Measurements {
&self
.wall_clock_times()
.iter()
.map(|t| t.value_in::<Second>()) // TODO
.map(|t| t.value_in::<second>()) // TODO
.collect::<Vec<_>>(),
)
}
+6 -6
View File
@@ -12,7 +12,7 @@ use std::time::Instant;
use crate::benchmark::benchmark_result::Parameter;
use crate::benchmark::executor::BenchmarkIteration;
use crate::benchmark::measurement::{Measurement, Measurements};
use crate::benchmark::quantity::{MilliSecond, Second};
use crate::benchmark::quantity::{const_time_from_seconds, Time, TimeQuantity};
use crate::command::Command;
use crate::options::{
CmdFailureAction, CommandOutputPolicy, ExecutorKind, Options, OutputStyleOption,
@@ -33,7 +33,7 @@ use colored::*;
use self::executor::Executor;
/// Threshold for warning about fast execution time
pub const MIN_EXECUTION_TIME: MilliSecond = MilliSecond::new(5.);
pub const MIN_EXECUTION_TIME: Time = const_time_from_seconds(0.005);
pub struct Benchmark<'a> {
number: usize,
@@ -262,7 +262,7 @@ impl<'a> Benchmark<'a> {
};
let preparation_result = run_preparation_command()?;
let preparation_overhead = preparation_result.map_or(Second::zero(), |res| {
let preparation_overhead = preparation_result.map_or(Time::zero(), |res| {
res.time_wall_clock + self.executor.time_overhead()
});
@@ -291,7 +291,7 @@ impl<'a> Benchmark<'a> {
}
let conclusion_result = run_conclusion_command()?;
let conclusion_overhead = conclusion_result.map_or(Second::zero(), |res| {
let conclusion_overhead = conclusion_result.map_or(Time::zero(), |res| {
res.time_wall_clock + self.executor.time_overhead()
});
@@ -301,7 +301,7 @@ impl<'a> Benchmark<'a> {
+ self.executor.time_overhead()
+ preparation_overhead
+ conclusion_overhead))
.get::<ratio>() as u64;
.get::<quantity::ratio>() as u64;
let count = {
let min = cmp::max(runs_in_min_time, self.options.run_bounds.min);
@@ -432,7 +432,7 @@ impl<'a> Benchmark<'a> {
&& measurements
.wall_clock_times()
.iter()
.any(|&t| t < MIN_EXECUTION_TIME.convert_to::<Second>())
.any(|&t| t < MIN_EXECUTION_TIME)
{
warnings.push(Warnings::FastExecutionTime);
}
+148 -216
View File
@@ -1,229 +1,146 @@
use std::{
fmt::{self, Display, Formatter},
ops::{Add, Div, Sub},
};
use core::f64;
use std::marker::PhantomData;
use serde::{ser::SerializeStruct, Serialize, Serializer};
use serde::ser::SerializeStruct;
use serde::Serializer;
use uom::{si, Conversion};
pub trait IsQuantity {
type Value;
pub use uom::si::information::{byte, kibibyte};
pub use uom::si::ratio::ratio;
pub use uom::si::time::{microsecond, millisecond, nanosecond, second};
const IS_TIME: bool;
const METRIC_PREFIX_TIME: i32;
const IS_INFORMATION: bool;
const BINARY_PREFIX_INFORMATION: i32;
pub use si::f64::Ratio;
pub use si::f64::Time;
pub use si::u64::Information;
fn unsafe_from(value: Self::Value) -> Self;
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd)] // TODO: check partialord
pub struct Quantity<
Value,
const IS_TIME: bool,
const METRIC_PREFIX_TIME: i32,
const IS_INFORMATION: bool,
const BINARY_PREFIX_INFORMATION: i32,
>(Value);
impl<
Value,
const IS_TIME: bool,
const METRIC_PREFIX_TIME: i32,
const IS_INFORMATION: bool,
const BINARY_PREFIX_INFORMATION: i32,
> IsQuantity
for Quantity<Value, IS_TIME, METRIC_PREFIX_TIME, IS_INFORMATION, BINARY_PREFIX_INFORMATION>
{
type Value = Value;
const IS_TIME: bool = IS_TIME;
const METRIC_PREFIX_TIME: i32 = METRIC_PREFIX_TIME;
const IS_INFORMATION: bool = IS_INFORMATION;
const BINARY_PREFIX_INFORMATION: i32 = BINARY_PREFIX_INFORMATION;
fn unsafe_from(value: Self::Value) -> Self {
Self(value)
}
}
type Time<const PREFIX: i32> = Quantity<f64, true, PREFIX, false, 0>;
type Information<const PREFIX: i32> = Quantity<u64, false, 0, true, PREFIX>;
pub type Second = Time<0>;
pub type MilliSecond = Time<-3>;
pub type MicroSecond = Time<-6>;
pub type Byte = Information<0>;
pub type KibiByte = Information<10>;
pub type MebiByte = Information<20>;
pub type GibiByte = Information<30>;
pub type TebiByte = Information<40>;
impl<
Value: Copy + Default,
const IS_TIME: bool,
const METRIC_PREFIX_TIME: i32,
const IS_INFORMATION: bool,
const BINARY_PREFIX_INFORMATION: i32,
> Quantity<Value, IS_TIME, METRIC_PREFIX_TIME, IS_INFORMATION, BINARY_PREFIX_INFORMATION>
{
pub const fn new(value: Value) -> Self {
Self(value)
pub trait TimeQuantity {
fn zero() -> Time {
Time::new::<second>(0.0)
}
pub fn zero() -> Self {
Self::new(Value::default())
fn from_seconds(value: f64) -> Time {
Time::new::<second>(value)
}
pub fn value_in<TargetUnit: IsQuantity>(&self) -> Value {
const {
assert!(IS_TIME == TargetUnit::IS_TIME);
assert!(METRIC_PREFIX_TIME == TargetUnit::METRIC_PREFIX_TIME);
assert!(IS_INFORMATION == TargetUnit::IS_INFORMATION);
assert!(BINARY_PREFIX_INFORMATION == TargetUnit::BINARY_PREFIX_INFORMATION);
}
self.0
fn from_milliseconds(value: f64) -> Time {
Time::new::<millisecond>(value)
}
const fn unit_name(&self) -> &'static str {
match (IS_TIME, IS_INFORMATION) {
(true, false) => match METRIC_PREFIX_TIME {
-6 => "µs",
-3 => "ms",
0 => "s",
_ => unreachable!(),
},
(false, true) => match BINARY_PREFIX_INFORMATION {
0 => "B",
10 => "KiB",
20 => "MiB",
30 => "GiB",
40 => "TiB",
_ => unreachable!(),
},
_ => unreachable!(),
}
fn from_microseconds(value: f64) -> Time {
Time::new::<microsecond>(value)
}
const fn unit_name_long(&self) -> &'static str {
match (IS_TIME, IS_INFORMATION) {
(true, false) => match METRIC_PREFIX_TIME {
-6 => "microsecond",
-3 => "millisecond",
0 => "second",
_ => unreachable!(),
},
(false, true) => match BINARY_PREFIX_INFORMATION {
0 => "byte",
10 => "kibibyte",
20 => "mebibyte",
30 => "gibibyte",
40 => "tebibyte",
_ => unreachable!(),
},
_ => unreachable!(),
}
fn from_nanoseconds(value: f64) -> Time {
Time::new::<nanosecond>(value)
}
}
impl<const METRIC_PREFIX_TIME: i32> Time<METRIC_PREFIX_TIME> {
pub fn convert_to<TargetUnit: IsQuantity<Value = f64>>(&self) -> TargetUnit {
let factor = 10_f64.powi(METRIC_PREFIX_TIME - TargetUnit::METRIC_PREFIX_TIME);
// fn square(&self) -> Time;
TargetUnit::unsafe_from(self.0 * factor)
}
}
impl<const METRIC_PREFIX_TIME: i32> Add<Time<METRIC_PREFIX_TIME>> for Time<METRIC_PREFIX_TIME> {
type Output = Time<METRIC_PREFIX_TIME>;
fn add(self, rhs: Time<METRIC_PREFIX_TIME>) -> Self::Output {
Time::new(self.0 + rhs.0)
}
}
impl<const METRIC_PREFIX_TIME: i32> Sub<Time<METRIC_PREFIX_TIME>> for Time<METRIC_PREFIX_TIME> {
type Output = Time<METRIC_PREFIX_TIME>;
fn sub(self, rhs: Time<METRIC_PREFIX_TIME>) -> Self::Output {
Time::new(self.0 - rhs.0)
}
}
impl<const METRIC_PREFIX_TIME: i32> Div<Time<METRIC_PREFIX_TIME>> for Time<METRIC_PREFIX_TIME> {
type Output = f64;
fn div(self, rhs: Time<METRIC_PREFIX_TIME>) -> Self::Output {
self.0 / rhs.0
}
}
impl<const METRIC_PREFIX_TIME: i32> Display for Time<METRIC_PREFIX_TIME> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let prefix = match METRIC_PREFIX_TIME {
-6 => "µ",
-3 => "m",
0 => "s",
_ => unreachable!(),
};
write!(f, "{} {}s", self.0, prefix)
}
}
impl<const BINARY_PREFIX_INFORMATION: i32> Display for Information<BINARY_PREFIX_INFORMATION> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let prefix = match BINARY_PREFIX_INFORMATION {
0 => "",
10 => "Ki",
20 => "Mi",
30 => "Gi",
40 => "Ti",
_ => unreachable!(),
};
write!(f, "{} {}B", self.0, prefix)
}
}
impl<
Value: Copy + Default + Serialize,
const IS_TIME: bool,
const METRIC_PREFIX_TIME: i32,
const IS_INFORMATION: bool,
const BINARY_PREFIX_INFORMATION: i32,
> Serialize
for Quantity<Value, IS_TIME, METRIC_PREFIX_TIME, IS_INFORMATION, BINARY_PREFIX_INFORMATION>
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
fn value_in<U>(&self) -> f64
where
S: Serializer,
U: si::time::Unit + Conversion<f64, T = f64>;
fn to_string<U>(&self, u: U) -> String
where
U: si::time::Unit + Conversion<f64, T = f64>;
}
impl TimeQuantity for Time {
fn value_in<U>(&self) -> f64
where
U: si::time::Unit + Conversion<f64, T = f64>,
{
let mut state = serializer.serialize_struct("Quantity", 2)?;
state.serialize_field("value", &self.0)?;
state.serialize_field("unit", self.unit_name())?;
state.serialize_field("unit_long", self.unit_name_long())?;
state.end()
self.get::<U>()
}
fn to_string<U>(&self, u: U) -> String
where
U: si::time::Unit + Conversion<f64, T = f64>,
{
format!(
"{:.3}",
self.into_format_args(u, uom::fmt::DisplayStyle::Abbreviation)
)
}
}
pub const fn const_time_from_seconds(value: f64) -> Time {
// Quantity::new in uom is not yet const: https://docs.rs/uom/0.36.0/uom/si/struct.Quantity.html
Time {
dimension: PhantomData,
units: PhantomData,
value,
}
}
pub trait InformationQuantity {
fn zero() -> Information {
Information::new::<byte>(0)
}
fn from_bytes(value: u64) -> Information {
Information::new::<byte>(value)
}
fn from_kibibytes(value: u64) -> Information {
Information::new::<kibibyte>(value)
}
fn value_in<U>(&self) -> u64
where
U: si::information::Unit + Conversion<u64, T = uom::num_rational::Ratio<u64>>;
fn to_string<U>(&self, u: U) -> String
where
U: si::information::Unit + Conversion<u64, T = uom::num_rational::Ratio<u64>>;
}
impl InformationQuantity for Information {
fn value_in<U>(&self) -> u64
where
U: si::information::Unit + Conversion<u64, T = uom::num_rational::Ratio<u64>>,
{
self.get::<U>()
}
fn to_string<U>(&self, u: U) -> String
where
U: si::information::Unit + Conversion<u64, T = uom::num_rational::Ratio<u64>>,
{
format!(
"{}",
self.into_format_args(u, uom::fmt::DisplayStyle::Abbreviation)
)
}
}
pub fn serialize_time<S>(t: &Time, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = s.serialize_struct("Time", 3)?;
state.serialize_field("value", &t.value)?;
state.serialize_field("unit", "second")?;
state.end()
}
pub fn serialize_information<S>(i: &Information, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = s.serialize_struct("Information", 3)?;
state.serialize_field("value", &i.value)?;
state.serialize_field("unit", "byte")?;
state.end()
}
macro_rules! quantity_fn {
($name:ident, $unwrapped_values:ident, $body:expr) => {
pub fn $name<
const IS_TIME: bool,
const METRIC_PREFIX_TIME: i32,
const IS_INFORMATION: bool,
const BINARY_PREFIX_INFORMATION: i32,
>(
values: &[Quantity<
f64,
IS_TIME,
METRIC_PREFIX_TIME,
IS_INFORMATION,
BINARY_PREFIX_INFORMATION,
>],
) -> Quantity<f64, IS_TIME, METRIC_PREFIX_TIME, IS_INFORMATION, BINARY_PREFIX_INFORMATION> {
let $unwrapped_values: Vec<f64> = values.iter().map(|v| v.0).collect();
pub fn $name(values: &[Time]) -> Time {
let $unwrapped_values: Vec<_> = values.iter().map(|q| q.value_in::<second>()).collect();
let result_value = $body;
Quantity::new(result_value)
Time::new::<second>(result_value)
}
};
}
@@ -238,29 +155,44 @@ quantity_fn!(standard_deviation, values, {
});
#[test]
fn test_quantity() {
let time = MilliSecond::new(123.4);
assert_eq!(time.value_in::<MilliSecond>(), 123.4);
fn test_time() {
let time = Time::from_milliseconds(123.4);
assert_eq!(time.value_in::<millisecond>(), 123.4);
let time_s = time.convert_to::<Second>();
approx::assert_relative_eq!(time_s.value_in::<Second>(), 0.1234);
let time_s = time.value_in::<second>();
approx::assert_relative_eq!(time_s, 0.1234);
let time_us = time.convert_to::<MicroSecond>();
approx::assert_relative_eq!(time_us.value_in::<MicroSecond>(), 123400.0);
let time_us = time.value_in::<microsecond>();
approx::assert_relative_eq!(time_us, 123400.0);
}
#[test]
fn test_information() {
let information = Information::from_kibibytes(8);
assert_eq!(information.value_in::<byte>(), 8192);
let information_kib = information.value_in::<kibibyte>();
assert_eq!(information_kib, 8);
}
#[test]
fn test_format() {
let time = MilliSecond::new(123.4);
assert_eq!(time.to_string(), "123.4 ms");
let time = Time::from_milliseconds(123.4);
assert_eq!(time.to_string(second), "0.123 s");
assert_eq!(time.to_string(millisecond), "123.400 ms");
assert_eq!(time.to_string(microsecond), "123400.000 µs");
let peak_memory_usage = KibiByte::new(8);
assert_eq!(peak_memory_usage.to_string(), "8 KiB");
let peak_memory_usage = Information::from_kibibytes(8);
assert_eq!(peak_memory_usage.to_string(byte), "8192 B");
assert_eq!(peak_memory_usage.to_string(kibibyte), "8 KiB");
}
#[test]
fn test_mean() {
let values = vec![MilliSecond::new(123.4), MilliSecond::new(234.5)];
let values = vec![
Time::from_milliseconds(123.4),
Time::from_milliseconds(234.5),
];
let result = mean(&values);
assert_eq!(result.to_string(), "178.95 ms");
assert_eq!(result.to_string(millisecond), "178.950 ms");
}
+15 -12
View File
@@ -1,7 +1,10 @@
use std::cmp::Ordering;
use super::benchmark_result::BenchmarkResult;
use crate::{benchmark::quantity::Second, options::SortOrder};
use crate::{
benchmark::quantity::{self, Ratio, Time, TimeQuantity},
options::SortOrder,
};
#[derive(Debug)]
pub struct BenchmarkResultWithRelativeSpeed<'a> {
@@ -52,8 +55,8 @@ fn compute_relative_speeds<'a>(
let is_reference = std::ptr::eq(result, reference);
let relative_ordering = compare_mean_time(result, reference);
if result.mean_wall_clock_time() == Second::zero()
|| reference.mean_wall_clock_time() == Second::zero()
if result.mean_wall_clock_time() == Time::zero()
|| reference.mean_wall_clock_time() == Time::zero()
{
return BenchmarkResultWithRelativeSpeed {
result,
@@ -66,7 +69,7 @@ fn compute_relative_speeds<'a>(
let ratio = match relative_ordering {
Ordering::Less => reference.mean_wall_clock_time() / result.mean_wall_clock_time(),
Ordering::Equal => 1.0,
Ordering::Equal => Ratio::new::<quantity::ratio>(1.0),
Ordering::Greater => {
result.mean_wall_clock_time() / reference.mean_wall_clock_time()
}
@@ -114,8 +117,8 @@ pub fn compute_with_check_from_reference<'a>(
reference: &'a BenchmarkResult,
sort_order: SortOrder,
) -> Option<Vec<BenchmarkResultWithRelativeSpeed<'a>>> {
if fastest_of(results).mean_wall_clock_time() == Second::zero()
|| reference.mean_wall_clock_time() == Second::zero()
if fastest_of(results).mean_wall_clock_time() == Time::zero()
|| reference.mean_wall_clock_time() == Time::zero()
{
return None;
}
@@ -129,7 +132,7 @@ pub fn compute_with_check(
) -> Option<Vec<BenchmarkResultWithRelativeSpeed<'_>>> {
let fastest = fastest_of(results);
if fastest.mean_wall_clock_time() == Second::zero() {
if fastest.mean_wall_clock_time() == Time::zero() {
return None;
}
@@ -152,17 +155,17 @@ fn create_result(name: &str, mean: f64) -> BenchmarkResult {
use crate::benchmark::{
measurement::{Measurement, Measurements},
quantity::Byte,
quantity::{Information, InformationQuantity},
};
BenchmarkResult {
command: name.into(),
measurements: Measurements {
measurements: vec![Measurement {
time_wall_clock: Second::new(mean),
time_user: Second::new(mean),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(mean),
time_user: Time::from_seconds(mean),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
}],
},
+16 -32
View File
@@ -208,73 +208,57 @@ fn scheduler_basic() -> Result<()> {
measurements:
- time_wall_clock:
value: 0.123
unit: s
unit_long: second
unit: second
time_user:
value: 0
unit: s
unit_long: second
unit: second
time_system:
value: 0
unit: s
unit_long: second
unit: second
peak_memory_usage:
value: 0
unit: B
unit_long: byte
unit: byte
exit_code: 0
- time_wall_clock:
value: 0.123
unit: s
unit_long: second
unit: second
time_user:
value: 0
unit: s
unit_long: second
unit: second
time_system:
value: 0
unit: s
unit_long: second
unit: second
peak_memory_usage:
value: 0
unit: B
unit_long: byte
unit: byte
exit_code: 0
- command: sleep 0.456
measurements:
- time_wall_clock:
value: 0.456
unit: s
unit_long: second
unit: second
time_user:
value: 0
unit: s
unit_long: second
unit: second
time_system:
value: 0
unit: s
unit_long: second
unit: second
peak_memory_usage:
value: 0
unit: B
unit_long: byte
unit: byte
exit_code: 0
- time_wall_clock:
value: 0.456
unit: s
unit_long: second
unit: second
time_user:
value: 0
unit: s
unit_long: second
unit: second
time_system:
value: 0
unit: s
unit_long: second
unit: second
peak_memory_usage:
value: 0
unit: B
unit_long: byte
unit: byte
exit_code: 0
"#);
+27 -27
View File
@@ -4,7 +4,7 @@ use csv::WriterBuilder;
use super::Exporter;
use crate::benchmark::benchmark_result::BenchmarkResult;
use crate::benchmark::quantity::Second;
use crate::benchmark::quantity::{second, TimeQuantity};
use crate::options::SortOrder;
use crate::quantity::{FormatQuantity, TimeUnit};
@@ -53,7 +53,7 @@ impl Exporter for CsvExporter {
res.measurements.min(),
res.measurements.max(),
] {
fields.push(Cow::Owned(f.value_in::<Second>().to_string().into_bytes()))
fields.push(Cow::Owned(f.value_in::<second>().to_string().into_bytes()))
}
for v in res.parameters.values() {
fields.push(Cow::Borrowed(v.value.as_bytes()))
@@ -69,7 +69,7 @@ impl Exporter for CsvExporter {
fn test_csv() {
use crate::benchmark::benchmark_result::Parameter;
use crate::benchmark::measurement::{Measurement, Measurements};
use crate::benchmark::quantity::{Byte, Second};
use crate::benchmark::quantity::{Information, InformationQuantity, Time, TimeQuantity};
use std::collections::BTreeMap;
use std::process::ExitStatus;
@@ -81,24 +81,24 @@ fn test_csv() {
command: String::from("command_a"),
measurements: Measurements::new(vec![
Measurement {
time_wall_clock: Second::new(7.0),
time_user: Second::new(7.0),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(7.0),
time_user: Time::from_seconds(7.0),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(8.0),
time_user: Second::new(8.0),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(8.0),
time_user: Time::from_seconds(8.0),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(12.0),
time_user: Second::new(12.0),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(12.0),
time_user: Time::from_seconds(12.0),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
]),
@@ -125,24 +125,24 @@ fn test_csv() {
command: String::from("command_b"),
measurements: Measurements::new(vec![
Measurement {
time_wall_clock: Second::new(17.0),
time_user: Second::new(17.0),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(17.0),
time_user: Time::from_seconds(17.0),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(18.0),
time_user: Second::new(18.0),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(18.0),
time_user: Time::from_seconds(18.0),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(19.0),
time_user: Second::new(19.0),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(19.0),
time_user: Time::from_seconds(19.0),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
]),
+97 -97
View File
@@ -1,7 +1,7 @@
use super::Exporter;
use crate::benchmark::benchmark_result::BenchmarkResult;
use crate::benchmark::measurement::{Measurement, Measurements};
use crate::benchmark::quantity::{Byte, Second};
use crate::benchmark::quantity::{Information, InformationQuantity, Time, TimeQuantity};
use crate::export::asciidoc::AsciidocExporter;
use crate::export::orgmode::OrgmodeExporter;
use crate::quantity::{byte, second, Information, Time, TimeUnit, Zero};
@@ -31,24 +31,24 @@ fn test_markup_export_auto_ms() {
command: String::from("sleep 0.1"),
measurements: Measurements::new(vec![
Measurement {
time_wall_clock: Second::new(0.09),
time_user: Second::new(0.09),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(0.09),
time_user: Time::from_seconds(0.09),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(0.10),
time_user: Second::new(0.10),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(0.10),
time_user: Time::from_seconds(0.10),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(0.14),
time_user: Second::new(0.14),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(0.14),
time_user: Time::from_seconds(0.14),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
]),
@@ -58,24 +58,24 @@ fn test_markup_export_auto_ms() {
command: String::from("sleep 2"),
measurements: Measurements::new(vec![
Measurement {
time_wall_clock: Second::new(2.0),
time_user: Second::new(2.0),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(2.0),
time_user: Time::from_seconds(2.0),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(3.0),
time_user: Second::new(3.0),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(3.0),
time_user: Time::from_seconds(3.0),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(4.0),
time_user: Second::new(4.0),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(4.0),
time_user: Time::from_seconds(4.0),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
]),
@@ -130,24 +130,24 @@ fn test_markup_export_auto_s() {
command: String::from("sleep 2"),
measurements: Measurements::new(vec![
Measurement {
time_wall_clock: Second::new(2.1),
time_user: Second::new(2.1),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(2.1),
time_user: Time::from_seconds(2.1),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(2.2),
time_user: Second::new(2.2),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(2.2),
time_user: Time::from_seconds(2.2),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(2.3),
time_user: Second::new(2.3),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(2.3),
time_user: Time::from_seconds(2.3),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
]),
@@ -157,24 +157,24 @@ fn test_markup_export_auto_s() {
command: String::from("sleep 0.1"),
measurements: Measurements::new(vec![
Measurement {
time_wall_clock: Second::new(0.1),
time_user: Second::new(0.1),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(0.1),
time_user: Time::from_seconds(0.1),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(0.2),
time_user: Second::new(0.2),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(0.2),
time_user: Time::from_seconds(0.2),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(0.3),
time_user: Second::new(0.3),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(0.3),
time_user: Time::from_seconds(0.3),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
]),
@@ -229,24 +229,24 @@ fn test_markup_export_manual_ms() {
command: String::from("sleep 2"),
measurements: Measurements::new(vec![
Measurement {
time_wall_clock: Second::new(2.1),
time_user: Second::new(2.1),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(2.1),
time_user: Time::from_seconds(2.1),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(2.2),
time_user: Second::new(2.2),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(2.2),
time_user: Time::from_seconds(2.2),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(2.3),
time_user: Second::new(2.3),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(2.3),
time_user: Time::from_seconds(2.3),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
]),
@@ -256,24 +256,24 @@ fn test_markup_export_manual_ms() {
command: String::from("sleep 0.1"),
measurements: Measurements::new(vec![
Measurement {
time_wall_clock: Second::new(0.1),
time_user: Second::new(0.1),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(0.1),
time_user: Time::from_seconds(0.1),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(0.2),
time_user: Second::new(0.2),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(0.2),
time_user: Time::from_seconds(0.2),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(0.3),
time_user: Second::new(0.3),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(0.3),
time_user: Time::from_seconds(0.3),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
]),
@@ -327,24 +327,24 @@ fn test_markup_export_manual_s() {
command: String::from("sleep 2"),
measurements: Measurements::new(vec![
Measurement {
time_wall_clock: Second::new(2.01),
time_user: Second::new(2.01),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(2.01),
time_user: Time::from_seconds(2.01),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(2.02),
time_user: Second::new(2.02),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(2.02),
time_user: Time::from_seconds(2.02),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(2.03),
time_user: Second::new(2.03),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(2.03),
time_user: Time::from_seconds(2.03),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
]),
@@ -354,24 +354,24 @@ fn test_markup_export_manual_s() {
command: String::from("sleep 0.1"),
measurements: Measurements::new(vec![
Measurement {
time_wall_clock: Second::new(0.11),
time_user: Second::new(0.11),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(0.11),
time_user: Time::from_seconds(0.11),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(0.12),
time_user: Second::new(0.12),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(0.12),
time_user: Time::from_seconds(0.12),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
Measurement {
time_wall_clock: Second::new(0.13),
time_user: Second::new(0.13),
time_system: Second::zero(),
peak_memory_usage: Byte::new(1024),
time_wall_clock: Time::from_seconds(0.13),
time_user: Time::from_seconds(0.13),
time_system: Time::zero(),
peak_memory_usage: Information::from_bytes(1024),
exit_status: ExitStatus::default(),
},
]),
+3 -3
View File
@@ -7,7 +7,7 @@ use std::{cmp, env, fmt, io};
use anyhow::{bail, ensure};
use clap::ArgMatches;
use crate::benchmark::quantity::Second;
use crate::benchmark::quantity::{Time, TimeQuantity};
use crate::command::Commands;
use crate::error::OptionsError;
use crate::util::units::Unit;
@@ -257,7 +257,7 @@ impl Default for Options {
Options {
run_bounds: RunBounds::default(),
warmup_count: 0,
min_benchmarking_time: Second::new(3.0),
min_benchmarking_time: Time::from_seconds(3.0),
command_failure_action: CmdFailureAction::RaiseError,
reference_command: None,
reference_name: None,
@@ -443,7 +443,7 @@ impl Options {
};
if let Some(time) = matches.get_one::<String>("min-benchmarking-time") {
options.min_benchmarking_time = Second::new(
options.min_benchmarking_time = Time::from_seconds(
time.parse::<f64>()
.map_err(|e| OptionsError::FloatParsingError("min-benchmarking-time", e))?,
);
+3 -2
View File
@@ -1,6 +1,6 @@
use std::fmt;
use crate::benchmark::quantity::Second;
use crate::benchmark::quantity::{millisecond, Time, TimeQuantity};
use crate::benchmark::MIN_EXECUTION_TIME;
use crate::output::format::format_duration;
@@ -22,10 +22,11 @@ impl fmt::Display for Warnings {
match *self {
Warnings::FastExecutionTime => write!(
f,
"Command took less than {MIN_EXECUTION_TIME} to complete. Note that the results might be \
"Command took less than {min_execution_time} to complete. Note that the results might be \
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.to_string(millisecond)
),
Warnings::NonZeroExitCode => write!(f, "Ignoring non-zero exit code."),
Warnings::SlowInitialRun(time_first_run, ref options) => write!(
+5 -5
View File
@@ -8,7 +8,7 @@ use std::process::{Child, ExitStatus};
use anyhow::Result;
use crate::benchmark::quantity::{Byte, Second};
use crate::benchmark::quantity::{Information, InformationQuantity, Time, TimeQuantity};
#[derive(Debug, Copy, Clone)]
struct ResourceUsage {
@@ -68,13 +68,13 @@ impl CPUTimer {
Self {}
}
pub fn stop(&self, child: Child) -> Result<(ExitStatus, Second, Second, Byte)> {
pub fn stop(&self, child: Child) -> Result<(ExitStatus, Time, Time, Information)> {
let (status, usage) = wait4(child)?;
Ok((
status,
Second::new(usage.user_usec),
Second::new(usage.system_usec),
Byte::new(u64::try_from(usage.memory_usage_byte).unwrap_or(0)),
Time::from_seconds(usage.user_usec),
Time::from_seconds(usage.system_usec),
Information::from_bytes(u64::try_from(usage.memory_usage_byte).unwrap_or(0)),
))
}
}
+4 -3
View File
@@ -1,6 +1,6 @@
use std::time::Instant;
use crate::benchmark::quantity::Second;
use crate::benchmark::quantity::{Time, TimeQuantity};
pub struct WallClockTimer {
start: Instant,
@@ -15,7 +15,8 @@ impl WallClockTimer {
pub fn stop(&self) -> Time {
let duration = self.start.elapsed();
// TODO
Second::new(duration.as_secs() as f64 + f64::from(duration.subsec_nanos()) * 1e-9)
Time::from_seconds(duration.as_secs() as f64)
+ Time::from_nanoseconds(duration.subsec_nanos() as f64)
}
}