Initial working version with child proc HANDLE.

Still very ugly, and more work needs to be done to make it all pretty again. Additionally, cleaned
up all the cfg attrs to shor version
This commit is contained in:
Steve Pentland authored and sharkdp committed 2018-02-13 21:02:32 +01:00
1 parent 79c375af0f
commit 9753eed85b
5 files changed
+72 -23

No files matched your search

+3 -3
View File
@@ -15,11 +15,11 @@ indicatif = "0.9"
statistical = "0.1"
atty = "0.2.2"
[target.'cfg(not(target_os = "windows"))'.dependencies]
[target.'cfg(not(windows))'.dependencies]
libc = "0.2"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3.4", features = [ "processthreadsapi", "minwindef"] }
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.4", features = ["processthreadsapi", "minwindef", "winnt"] }
[dependencies.clap]
version = "2"
+38 -4
View File
@@ -1,4 +1,5 @@
use std::io;
use std::process::ExitStatus;
use colored::*;
use statistical::{mean, standard_deviation};
@@ -10,9 +11,10 @@ use hyperfine::format::{format_duration, format_duration_unit};
use hyperfine::outlier_detection::{modified_zscores, OUTLIER_THRESHOLD};
use hyperfine::timer::Timer;
use hyperfine::timer::wallclocktimer::WallClockTimer;
use hyperfine::timer::cputimer::CPUTimer;
use hyperfine::timer::cputimer::get_process_times;
use hyperfine::shell::run_shell_command;
/// Results from timing a single shell command
#[derive(Debug, Copy, Clone)]
pub struct TimingResult {
@@ -42,12 +44,13 @@ pub fn time_shell_command(
shell_spawning_time: Option<TimingResult>,
) -> io::Result<(TimingResult, bool)> {
let wallclock_timer = WallClockTimer::start();
let cpu_timer = CPUTimer::start();
// let cpu_timer = CPUTimer::start();
let status = run_shell_command(shell_cmd)?;
let (mut time_user, mut time_system, status) = execute_and_time(shell_cmd)?;
// let status = run_shell_command(shell_cmd)?;
let mut time_real = wallclock_timer.stop();
let (mut time_user, mut time_system) = cpu_timer.stop();
// let (mut time_user, mut time_system) = cpu_timer.stop();
if failure_action == CmdFailureAction::RaiseError && !status.success() {
return Err(io::Error::new(
@@ -291,3 +294,34 @@ pub fn run_benchmark(
Ok(())
}
#[cfg(windows)]
fn execute_and_time(command: &str) -> io::Result<(f64, f64, ExitStatus)> {
use std::os::windows::io::AsRawHandle;
let mut child = run_shell_command(command)?;
let result = child.wait()?;
let handle = child.as_raw_handle();
let (user_usec, system_usec) = get_process_times(handle);
// Temp, bypassing timer and the stop method
let user = user_usec as f64 * 1e-6;
let system = system_usec as f64 * 1e-6;
Ok((user, system, result))
}
#[cfg(not(windows))]
fn execute_and_time(command: &str) -> io::Result<(f64, f64, ExitStatus)> {
use hyperfine::timer::cputimer::CPUTimer;
let cpu_timer = CPUTimer::start();
let status = run_shell_command(command)?;
let (mut time_user, mut time_system) = cpu_timer.stop();
Ok((time_user, time_system, status))
}
+11 -5
View File
@@ -1,8 +1,14 @@
use std::io;
use std::process::{Command, ExitStatus, Stdio};
use std::process::{Command, Stdio};
#[cfg(not(windows))]
use std::process::ExitStatus;
#[cfg(windows)]
use std::process::Child;
/// Run a standard shell command
#[cfg(not(target_os = "windows"))]
#[cfg(not(windows))]
pub fn run_shell_command(command: &str) -> io::Result<ExitStatus> {
Command::new("sh")
.arg("-c")
@@ -14,13 +20,13 @@ pub fn run_shell_command(command: &str) -> io::Result<ExitStatus> {
}
/// Run a Windows shell command using cmd.exe
#[cfg(target_os = "windows")]
pub fn run_shell_command(command: &str) -> io::Result<ExitStatus> {
#[cfg(windows)]
pub fn run_shell_command(command: &str) -> io::Result<Child> {
Command::new("cmd")
.arg("/C")
.arg(command)
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.spawn()
}
+17 -8
View File
@@ -1,6 +1,9 @@
use hyperfine::internal::Second;
use hyperfine::timer::Timer;
#[cfg(windows)]
use std::os::windows::io::RawHandle;
#[derive(Debug, Copy, Clone)]
struct CPUTimes {
/// Total amount of time spent executing in user mode
@@ -20,7 +23,7 @@ struct CPUInterval {
}
/// Read CPU execution times ('user' and 'system')
#[cfg(not(target_os = "windows"))]
#[cfg(not(windows))]
fn get_cpu_times() -> CPUTimes {
use libc::{getrusage, rusage, RUSAGE_CHILDREN};
use std::mem;
@@ -45,8 +48,17 @@ fn get_cpu_times() -> CPUTimes {
/// Read CPU execution times (dummy for now)
#[cfg(windows)]
fn get_cpu_times() -> CPUTimes {
use winapi::um::processthreadsapi::{GetCurrentProcess, GetProcessTimes};
CPUTimes {
user_usec : 0,
system_usec: 0,
}
}
#[cfg(windows)]
pub fn get_process_times(handle: RawHandle) -> (i64, i64) {
use winapi::um::processthreadsapi::GetProcessTimes;
use winapi::shared::minwindef::FILETIME;
use winapi::um::winnt::HANDLE;
// Winapi reports times as per 100 nanosecond
const HUNDRED_NS_PER_MS: i64 = 10;
@@ -69,9 +81,8 @@ fn get_cpu_times() -> CPUTimes {
};
let (user_usec, system_usec) = unsafe {
let handle = GetCurrentProcess();
let res = GetProcessTimes(
handle,
handle as HANDLE,
&mut _ctime,
&mut _etime,
&mut kernel_time,
@@ -81,6 +92,7 @@ fn get_cpu_times() -> CPUTimes {
// GetProcessTimes will exit with non-zero if success as per: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683223(v=vs.85).aspx
if res != 0 {
// Extract times as laid out here: https://support.microsoft.com/en-us/help/188768/info-working-with-the-filetime-structure
// Both user_time and kernel_time are spans that the proces spent in either.
let user: i64 = (((user_time.dwHighDateTime as i64) << 32) + user_time.dwLowDateTime as i64) / HUNDRED_NS_PER_MS;
let kernel: i64 = (((kernel_time.dwHighDateTime as i64) << 32) + kernel_time.dwLowDateTime as i64) / HUNDRED_NS_PER_MS;
(user, kernel)
@@ -89,10 +101,7 @@ fn get_cpu_times() -> CPUTimes {
}
};
CPUTimes {
user_usec,
system_usec,
}
(user_usec,system_usec)
}
/// Compute the time intervals in between two `CPUTimes` snapshots
+3 -3
View File
@@ -5,10 +5,10 @@ extern crate colored;
extern crate indicatif;
extern crate statistical;
#[cfg(not(target_os = "windows"))]
#[cfg(not(windows))]
extern crate libc;
#[cfg(target_os = "windows")]
#[cfg(windows)]
extern crate winapi;
#[cfg(test)]
@@ -149,7 +149,7 @@ fn main() {
OutputStyleOption::Basic
},
};
if options.output_style == OutputStyleOption::Basic {
colored::control::set_override(false);
}