mirror of
https://github.com/sharkdp/hyperfine.git
synced 2026-11-01 08:50:19 +00:00
Use uom
This commit is contained in:
1 parent
9ec7a9c920
commit
641451aea6
15 files changed
+459
-443
No files matched your search
Generated
+87
-9
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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,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
@@ -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)
|
||||
);
|
||||
}
|
||||
@@ -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<_>>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
@@ -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");
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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))?,
|
||||
);
|
||||
|
||||
@@ -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!(
|
||||
|
||||
@@ -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)),
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user