From 1ddf729c7afe49a3dee21aac5dd37e17c02857a6 Mon Sep 17 00:00:00 2001 From: Steve Pentland Date: Wed, 31 Jan 2018 17:51:07 -0500 Subject: [PATCH] Initial changes to skip libc for cpu time on windows Mark more non-windows as conditional --- Cargo.toml | 4 +- src/hyperfine/benchmark.rs | 86 +++++++++++++++++++++++++++++++++----- src/hyperfine/cputime.rs | 1 + src/main.rs | 5 ++- 4 files changed, 83 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a00143e..5614cca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,9 +13,11 @@ version = "0.4.0" colored = "1.6" indicatif = "0.9" statistical = "0.1" -libc = "0.2" atty = "0.2.2" +[target.'cfg(not(target_os = "windows"))'.dependencies] +libc = "0.2" + [dependencies.clap] version = "2" default-features = false diff --git a/src/hyperfine/benchmark.rs b/src/hyperfine/benchmark.rs index 4b65799..5c4868a 100644 --- a/src/hyperfine/benchmark.rs +++ b/src/hyperfine/benchmark.rs @@ -9,9 +9,11 @@ use hyperfine::internal::{get_progress_bar, max, min, CmdFailureAction, Hyperfin OutputStyleOption, Second, MIN_EXECUTION_TIME}; use hyperfine::warnings::Warnings; use hyperfine::format::{format_duration, format_duration_unit}; -use hyperfine::cputime::{cpu_time_interval, get_cpu_times}; use hyperfine::outlier_detection::{modified_zscores, OUTLIER_THRESHOLD}; +#[cfg(not(target_os = "windows"))] +use hyperfine::cputime::{cpu_time_interval, get_cpu_times}; + /// Results from timing a single shell command #[derive(Debug, Copy, Clone)] pub struct TimingResult { @@ -34,7 +36,9 @@ fn subtract_shell_spawning_time(time: Second, shell_spawning_time: Second) -> Se } } + /// Run the given shell command and measure the execution time +#[cfg(not(target_os = "windows"))] pub fn time_shell_command( shell_cmd: &str, failure_action: CmdFailureAction, @@ -87,6 +91,51 @@ pub fn time_shell_command( )) } +/// Run the given shell command and measure the execution time +#[cfg(target_os = "windows")] +pub fn time_shell_command( + shell_cmd: &str, + failure_action: CmdFailureAction, + shell_spawning_time: Option, +) -> io::Result<(TimingResult, bool)> { + let start = Instant::now(); + + let status = Command::new("sh") + .arg("-c") + .arg(shell_cmd) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status()?; + + let duration = start.elapsed(); + + if failure_action == CmdFailureAction::RaiseError && !status.success() { + return Err(io::Error::new( + io::ErrorKind::Other, + "Command terminated with non-zero exit code. \ + Use the '-i'/'--ignore-failure' option if you want to ignore this.", + )); + } + + // Real time + let mut time_real = duration.as_secs() as f64 + (duration.subsec_nanos() as f64) * 1e-9; + + // Correct for shell spawning time + if let Some(spawning_time) = shell_spawning_time { + time_real = subtract_shell_spawning_time(time_real, spawning_time.time_real); + } + + Ok(( + TimingResult { + time_real, + time_user: 0, + time_system: 0, + }, + status.success(), + )) +} + /// Measure the average shell spawning time pub fn mean_shell_spawning_time(style: &OutputStyleOption) -> io::Result { const COUNT: u64 = 200; @@ -252,15 +301,8 @@ pub fn run_benchmark( let (user_str, user_unit) = format_duration_unit(user_mean, None); let system_str = format_duration(system_mean, Some(user_unit)); - println!( - " Time ({} ± {}): {:>8} ± {:>8} [User: {}, System: {}]", - "mean".green().bold(), - "σ".green(), - mean_str.green().bold(), - stddev_str.green(), - user_str.blue(), - system_str.blue() - ); + output_times(mean_str, stddev_str, user_str, system_str); + println!(" "); println!( @@ -304,3 +346,27 @@ pub fn run_benchmark( Ok(()) } + +#[cfg(not(target_os = "windows"))] +fn output_times(mean_str: String, stddev_str: String, user_str: String, system_str: String) { + println!( + " Time ({} ± {}): {:>8} ± {:>8} [User: {}, System: {}]", + "mean".green().bold(), + "σ".green(), + mean_str.green().bold(), + stddev_str.green(), + user_str.blue(), + system_str.blue() + ); +} + +#[cfg(target_os = "windows")] +fn output_times(mean_str: String, stddev_str: String, _user_str: String, _system_str: String) { + println!( + " Time ({} ± {}): {:>8} ± {:>8}", + "mean".green().bold(), + "σ".green(), + mean_str.green().bold(), + stddev_str.green(), + ); +} diff --git a/src/hyperfine/cputime.rs b/src/hyperfine/cputime.rs index 74c6a48..19caa8c 100644 --- a/src/hyperfine/cputime.rs +++ b/src/hyperfine/cputime.rs @@ -1,4 +1,5 @@ use libc::{getrusage, rusage, RUSAGE_CHILDREN}; + use std::mem; use hyperfine::internal::Second; diff --git a/src/main.rs b/src/main.rs index da63489..4a1e55e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,13 @@ extern crate atty; - #[macro_use] extern crate clap; extern crate colored; extern crate indicatif; -extern crate libc; extern crate statistical; +#[cfg(not(target_os = "windows"))] +extern crate libc; + #[cfg(test)] #[macro_use] extern crate approx;