2018-02-05 18:22:59 -05:00
|
|
|
use std;
|
2018-02-02 17:28:52 +01:00
|
|
|
use std::io;
|
2018-02-07 19:03:52 -05:00
|
|
|
use std::process::{Command, ExitStatus, Stdio};
|
2018-02-04 20:19:24 -05:00
|
|
|
|
2019-05-07 11:55:38 +02:00
|
|
|
use crate::hyperfine::timer::get_cpu_timer;
|
2018-02-07 19:03:52 -05:00
|
|
|
|
|
|
|
|
/// Used to indicate the result of running a command
|
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
|
|
|
pub struct ExecuteResult {
|
|
|
|
|
/// The amount of user time the process used
|
|
|
|
|
pub user_time: f64,
|
|
|
|
|
|
|
|
|
|
/// The amount of cpu time the process used
|
|
|
|
|
pub system_time: f64,
|
|
|
|
|
|
|
|
|
|
/// The exit status of the process
|
|
|
|
|
pub status: ExitStatus,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Execute the given command and return a timing summary
|
|
|
|
|
#[cfg(windows)]
|
2018-11-21 19:55:58 +01:00
|
|
|
pub fn execute_and_time(
|
|
|
|
|
stdout: Stdio,
|
|
|
|
|
stderr: Stdio,
|
|
|
|
|
command: &str,
|
|
|
|
|
shell: &str,
|
|
|
|
|
) -> io::Result<ExecuteResult> {
|
2018-10-30 19:30:17 -07:00
|
|
|
let mut child = run_shell_command(stdout, stderr, command, shell)?;
|
2018-02-07 19:03:52 -05:00
|
|
|
let cpu_timer = get_cpu_timer(&child);
|
|
|
|
|
let status = child.wait()?;
|
|
|
|
|
|
|
|
|
|
let (user_time, system_time) = cpu_timer.stop();
|
|
|
|
|
Ok(ExecuteResult {
|
|
|
|
|
user_time,
|
|
|
|
|
system_time,
|
|
|
|
|
status,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Execute the given command and return a timing summary
|
|
|
|
|
#[cfg(not(windows))]
|
2018-11-21 19:55:58 +01:00
|
|
|
pub fn execute_and_time(
|
|
|
|
|
stdout: Stdio,
|
|
|
|
|
stderr: Stdio,
|
|
|
|
|
command: &str,
|
|
|
|
|
shell: &str,
|
|
|
|
|
) -> io::Result<ExecuteResult> {
|
2018-02-07 19:03:52 -05:00
|
|
|
let cpu_timer = get_cpu_timer();
|
|
|
|
|
|
2018-10-30 19:30:17 -07:00
|
|
|
let status = run_shell_command(stdout, stderr, command, shell)?;
|
2018-02-07 19:03:52 -05:00
|
|
|
|
|
|
|
|
let (user_time, system_time) = cpu_timer.stop();
|
|
|
|
|
|
|
|
|
|
Ok(ExecuteResult {
|
|
|
|
|
user_time,
|
|
|
|
|
system_time,
|
|
|
|
|
status,
|
|
|
|
|
})
|
|
|
|
|
}
|
2018-02-02 17:28:52 +01:00
|
|
|
|
2018-10-30 19:30:17 -07:00
|
|
|
/// Run a standard shell command using `sh -c`
|
2018-02-04 20:19:24 -05:00
|
|
|
#[cfg(not(windows))]
|
2018-05-22 22:57:51 +02:00
|
|
|
fn run_shell_command(
|
|
|
|
|
stdout: Stdio,
|
|
|
|
|
stderr: Stdio,
|
|
|
|
|
command: &str,
|
2018-10-30 19:30:17 -07:00
|
|
|
shell: &str,
|
2018-05-22 22:57:51 +02:00
|
|
|
) -> io::Result<std::process::ExitStatus> {
|
2018-10-30 19:30:17 -07:00
|
|
|
Command::new(shell)
|
2018-02-02 17:28:52 +01:00
|
|
|
.arg("-c")
|
|
|
|
|
.arg(command)
|
|
|
|
|
.stdin(Stdio::null())
|
2018-05-21 18:14:53 +02:00
|
|
|
.stdout(stdout)
|
2018-05-21 21:04:30 +02:00
|
|
|
.stderr(stderr)
|
2018-02-02 17:28:52 +01:00
|
|
|
.status()
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-30 19:30:17 -07:00
|
|
|
/// Run a Windows shell command using `cmd.exe /C`
|
2018-02-04 20:19:24 -05:00
|
|
|
#[cfg(windows)]
|
2018-05-22 22:57:51 +02:00
|
|
|
fn run_shell_command(
|
|
|
|
|
stdout: Stdio,
|
|
|
|
|
stderr: Stdio,
|
|
|
|
|
command: &str,
|
2018-10-30 19:30:17 -07:00
|
|
|
shell: &str,
|
2018-05-22 22:57:51 +02:00
|
|
|
) -> io::Result<std::process::Child> {
|
2018-10-30 19:30:17 -07:00
|
|
|
Command::new(shell)
|
2018-02-02 23:04:19 +01:00
|
|
|
.arg("/C")
|
2018-02-02 17:28:52 +01:00
|
|
|
.arg(command)
|
|
|
|
|
.stdin(Stdio::null())
|
2018-05-21 18:14:53 +02:00
|
|
|
.stdout(stdout)
|
2018-05-21 21:04:30 +02:00
|
|
|
.stderr(stderr)
|
2018-02-04 20:19:24 -05:00
|
|
|
.spawn()
|
2018-02-02 17:28:52 +01:00
|
|
|
}
|