mirror of
https://github.com/sharkdp/hyperfine.git
synced 2026-11-01 08:50:19 +00:00
Refactor execute and measure to shell, abstract away cpu timer
This commit is contained in:
1 parent
36cc649d13
commit
6c7e102a24
6 files changed
+117
-72
No files matched your search
@@ -1,5 +1,4 @@
|
||||
use std::io;
|
||||
use std::process::ExitStatus;
|
||||
|
||||
use colored::*;
|
||||
use statistical::{mean, standard_deviation};
|
||||
@@ -9,9 +8,9 @@ use hyperfine::internal::{get_progress_bar, max, min, CmdFailureAction, Hyperfin
|
||||
use hyperfine::warnings::Warnings;
|
||||
use hyperfine::format::{format_duration, format_duration_unit};
|
||||
use hyperfine::outlier_detection::{modified_zscores, OUTLIER_THRESHOLD};
|
||||
use hyperfine::timer::Timer;
|
||||
use hyperfine::timer::{TimerStart, TimerStop};
|
||||
use hyperfine::timer::wallclocktimer::WallClockTimer;
|
||||
use hyperfine::shell::run_shell_command;
|
||||
use hyperfine::shell::execute_and_time;
|
||||
|
||||
|
||||
/// Results from timing a single shell command
|
||||
@@ -293,44 +292,3 @@ pub fn run_benchmark(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct ExecuteResult {
|
||||
user_time: f64,
|
||||
system_time: f64,
|
||||
status: ExitStatus,
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn execute_and_time(command: &str) -> io::Result<ExecuteResult> {
|
||||
use hyperfine::timer::windows_timer::{CPUTimer, WindowsTimer};
|
||||
use std::os::windows::io::AsRawHandle;
|
||||
|
||||
let mut child = run_shell_command(command)?;
|
||||
let timer = CPUTimer::start(child.as_raw_handle());
|
||||
let status = child.wait()?;
|
||||
|
||||
let (user_time, system_time) = timer.stop();
|
||||
Ok(ExecuteResult {
|
||||
user_time,
|
||||
system_time,
|
||||
status,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn execute_and_time(command: &str) -> io::Result<ExecuteResult> {
|
||||
use hyperfine::timer::unix_timer::CPUTimer;
|
||||
|
||||
let cpu_timer = CPUTimer::start();
|
||||
|
||||
let status = run_shell_command(command)?;
|
||||
|
||||
let (user_time, system_time) = cpu_timer.stop();
|
||||
|
||||
Ok(ExecuteResult {
|
||||
user_time,
|
||||
system_time,
|
||||
status,
|
||||
})
|
||||
}
|
||||
+48
-3
@@ -1,11 +1,56 @@
|
||||
use std;
|
||||
use std::io;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::process::{Command, ExitStatus, Stdio};
|
||||
|
||||
use hyperfine::timer::get_cpu_timer;
|
||||
|
||||
/// 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)]
|
||||
pub fn execute_and_time(command: &str) -> io::Result<ExecuteResult> {
|
||||
let mut child = run_shell_command(command)?;
|
||||
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))]
|
||||
pub fn execute_and_time(command: &str) -> io::Result<ExecuteResult> {
|
||||
let cpu_timer = get_cpu_timer();
|
||||
|
||||
let status = run_shell_command(command)?;
|
||||
|
||||
let (user_time, system_time) = cpu_timer.stop();
|
||||
|
||||
Ok(ExecuteResult {
|
||||
user_time,
|
||||
system_time,
|
||||
status,
|
||||
})
|
||||
}
|
||||
|
||||
/// Run a standard shell command
|
||||
#[cfg(not(windows))]
|
||||
pub fn run_shell_command(command: &str) -> io::Result<std::process::ExitStatus> {
|
||||
fn run_shell_command(command: &str) -> io::Result<std::process::ExitStatus> {
|
||||
Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(command)
|
||||
@@ -17,7 +62,7 @@ pub fn run_shell_command(command: &str) -> io::Result<std::process::ExitStatus>
|
||||
|
||||
/// Run a Windows shell command using cmd.exe
|
||||
#[cfg(windows)]
|
||||
pub fn run_shell_command(command: &str) -> io::Result<std::process::Child> {
|
||||
fn run_shell_command(command: &str) -> io::Result<std::process::Child> {
|
||||
Command::new("cmd")
|
||||
.arg("/C")
|
||||
.arg(command)
|
||||
|
||||
@@ -3,15 +3,33 @@ mod internal;
|
||||
pub mod wallclocktimer;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub mod unix_timer;
|
||||
mod unix_timer;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub use self::unix_timer::get_cpu_timer;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub mod windows_timer;
|
||||
mod windows_timer;
|
||||
|
||||
/// Defines a general timer with start/stop functionality.
|
||||
pub trait Timer {
|
||||
type Result;
|
||||
#[cfg(windows)]
|
||||
pub use self::windows_timer::get_cpu_timer;
|
||||
|
||||
use std::process::Child;
|
||||
|
||||
pub trait Timer
|
||||
where
|
||||
Self: TimerStart + TimerStop,
|
||||
{
|
||||
}
|
||||
|
||||
/// Defines start functionality of a timer.
|
||||
pub trait TimerStart {
|
||||
fn start() -> Self;
|
||||
fn start_for_process(process: &Child) -> Self;
|
||||
}
|
||||
|
||||
/// Defines stop functionality of a timer.
|
||||
pub trait TimerStop {
|
||||
type Result;
|
||||
fn stop(&self) -> Self::Result;
|
||||
}
|
||||
@@ -1,24 +1,35 @@
|
||||
#![cfg(not(windows))]
|
||||
|
||||
use super::internal::{CPUInterval, CPUTimes};
|
||||
use hyperfine::timer::Timer;
|
||||
use hyperfine::timer::{TimerStart, TimerStop};
|
||||
use hyperfine::internal::Second;
|
||||
|
||||
use std::mem;
|
||||
use std::process::Child;
|
||||
|
||||
pub struct CPUTimer {
|
||||
pub fn get_cpu_timer() -> Box<TimerStop<Result = (Second, Second)>> {
|
||||
Box::new(CPUTimer::start())
|
||||
}
|
||||
|
||||
struct CPUTimer {
|
||||
start_cpu: CPUTimes,
|
||||
}
|
||||
|
||||
impl Timer for CPUTimer {
|
||||
type Result = (Second, Second);
|
||||
|
||||
impl TimerStart for CPUTimer {
|
||||
fn start() -> Self {
|
||||
CPUTimer {
|
||||
start_cpu: get_cpu_times(),
|
||||
}
|
||||
}
|
||||
|
||||
fn start_for_process(_: &Child) -> Self {
|
||||
Self::start()
|
||||
}
|
||||
}
|
||||
|
||||
impl TimerStop for CPUTimer {
|
||||
type Result = (Second, Second);
|
||||
|
||||
fn stop(&self) -> Self::Result {
|
||||
let end_cpu = get_cpu_times();
|
||||
let cpu_interval = cpu_time_interval(&self.start_cpu, &end_cpu);
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
use std::process::Child;
|
||||
use std::time::Instant;
|
||||
|
||||
use hyperfine::internal::Second;
|
||||
use hyperfine::timer::Timer;
|
||||
use hyperfine::timer::{TimerStart, TimerStop};
|
||||
|
||||
pub struct WallClockTimer {
|
||||
start: Instant,
|
||||
}
|
||||
|
||||
impl Timer for WallClockTimer {
|
||||
type Result = Second;
|
||||
|
||||
impl TimerStart for WallClockTimer {
|
||||
fn start() -> WallClockTimer {
|
||||
WallClockTimer {
|
||||
start: Instant::now(),
|
||||
}
|
||||
}
|
||||
|
||||
fn start_for_process(_: &Child) -> Self {
|
||||
Self::start()
|
||||
}
|
||||
}
|
||||
|
||||
impl TimerStop for WallClockTimer {
|
||||
type Result = Second;
|
||||
|
||||
fn stop(&self) -> Second {
|
||||
let duration = self.start.elapsed();
|
||||
duration.as_secs() as f64 + (duration.subsec_nanos() as f64) * 1e-9
|
||||
|
||||
@@ -2,33 +2,39 @@
|
||||
|
||||
use super::internal::CPUTimes;
|
||||
use hyperfine::internal::Second;
|
||||
use hyperfine::timer::{TimerStart, TimerStop};
|
||||
|
||||
use winapi::um::processthreadsapi::GetProcessTimes;
|
||||
use winapi::um::winnt::HANDLE;
|
||||
|
||||
use std::mem;
|
||||
use std::os::windows::io::RawHandle;
|
||||
use std::os::windows::io::{AsRawHandle, RawHandle};
|
||||
use std::process::Child;
|
||||
|
||||
const HUNDRED_NS_PER_MS: i64 = 10;
|
||||
|
||||
pub trait WindowsTimer {
|
||||
type Result;
|
||||
|
||||
fn start(handle: RawHandle) -> Self;
|
||||
fn stop(&self) -> Self::Result;
|
||||
pub fn get_cpu_timer(process: &Child) -> Box<TimerStop<Result=(Second,Second)>> {
|
||||
Box::new(CPUTimer::start_for_process(process))
|
||||
}
|
||||
|
||||
pub struct CPUTimer {
|
||||
struct CPUTimer {
|
||||
handle: RawHandle,
|
||||
}
|
||||
|
||||
impl WindowsTimer for CPUTimer {
|
||||
type Result = (Second, Second);
|
||||
impl TimerStart for CPUTimer {
|
||||
|
||||
fn start(handle: RawHandle) -> Self {
|
||||
CPUTimer { handle }
|
||||
fn start() -> Self {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn start_for_process(process: &Child) -> Self {
|
||||
CPUTimer { handle: process.as_raw_handle() }
|
||||
}
|
||||
}
|
||||
|
||||
impl TimerStop for CPUTimer {
|
||||
type Result = (Second, Second);
|
||||
|
||||
fn stop(&self) -> Self::Result {
|
||||
let times = get_cpu_times(self.handle);
|
||||
(times.user_usec as f64 * 1e-6, times.system_usec as f64 * 1e-6)
|
||||
|
||||
Reference in new issue
Block a user