Refactor timer module

This commit is contained in:
David Peter authored and David Peter committed 2022-02-22 10:51:06 +01:00
1 parent f029a46ff9
commit defafdf707
6 files changed
+18 -73

No files matched your search

-1
View File
@@ -5,7 +5,6 @@ use crate::options::{CmdFailureAction, CommandOutputPolicy, Options, OutputStyle
use crate::output::progress_bar::get_progress_bar; use crate::output::progress_bar::get_progress_bar;
use crate::shell::execute_and_time; use crate::shell::execute_and_time;
use crate::timer::wallclocktimer::WallClockTimer; use crate::timer::wallclocktimer::WallClockTimer;
use crate::timer::{TimerStart, TimerStop};
use crate::util::units::Second; use crate::util::units::Second;
use super::timing_result::TimingResult; use super::timing_result::TimingResult;
+2 -3
View File
@@ -1,7 +1,6 @@
use std::process::{ExitStatus, Stdio}; use std::process::{ExitStatus, Stdio};
use crate::options::Shell; use crate::options::Shell;
use crate::timer::get_cpu_timer;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
@@ -30,7 +29,7 @@ pub fn execute_and_time(
command: &str, command: &str,
shell: &Shell, shell: &Shell,
) -> Result<ExecuteResult> { ) -> Result<ExecuteResult> {
let cpu_timer = get_cpu_timer(); let cpu_timer = crate::timer::unix_timer::CPUTimer::start();
let status = shell let status = shell
.command() .command()
@@ -76,7 +75,7 @@ pub fn execute_and_time(
.stderr(stderr) .stderr(stderr)
.spawn() .spawn()
.with_context(|| format!("Failed to run command '{}'", command))?; .with_context(|| format!("Failed to run command '{}'", command))?;
let cpu_timer = get_cpu_timer(&child); let cpu_timer = crate::timer::windows_timer::CPUTimer::start_for_process(&child);
let status = child.wait()?; let status = child.wait()?;
let (user_time, system_time) = cpu_timer.stop(); let (user_time, system_time) = cpu_timer.stop();
+2 -20
View File
@@ -1,30 +1,12 @@
use std::process::Child;
use crate::util::units::Second; use crate::util::units::Second;
pub mod wallclocktimer; pub mod wallclocktimer;
#[cfg(windows)] #[cfg(windows)]
mod windows_timer; pub mod windows_timer;
#[cfg(windows)]
pub use self::windows_timer::get_cpu_timer;
#[cfg(not(windows))] #[cfg(not(windows))]
mod unix_timer; pub mod unix_timer;
#[cfg(not(windows))]
pub use self::unix_timer::get_cpu_timer;
/// 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;
}
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct CPUTimes { pub struct CPUTimes {
+5 -18
View File
@@ -1,35 +1,22 @@
#![cfg(not(windows))] #![cfg(not(windows))]
use std::mem; use std::mem;
use std::process::Child;
use crate::timer::{CPUInterval, CPUTimes, TimerStart, TimerStop}; use crate::timer::{CPUInterval, CPUTimes};
use crate::util::units::Second; use crate::util::units::Second;
pub fn get_cpu_timer() -> Box<dyn TimerStop<Result = (Second, Second)>> { pub struct CPUTimer {
Box::new(CPUTimer::start())
}
struct CPUTimer {
start_cpu: CPUTimes, start_cpu: CPUTimes,
} }
impl TimerStart for CPUTimer { impl CPUTimer {
fn start() -> Self { pub fn start() -> Self {
CPUTimer { CPUTimer {
start_cpu: get_cpu_times(), start_cpu: get_cpu_times(),
} }
} }
fn start_for_process(_: &Child) -> Self { pub fn stop(&self) -> (Second, Second) {
Self::start()
}
}
impl TimerStop for CPUTimer {
type Result = (Second, Second);
fn stop(&self) -> Self::Result {
let end_cpu = get_cpu_times(); let end_cpu = get_cpu_times();
let cpu_interval = cpu_time_interval(&self.start_cpu, &end_cpu); let cpu_interval = cpu_time_interval(&self.start_cpu, &end_cpu);
(cpu_interval.user, cpu_interval.system) (cpu_interval.user, cpu_interval.system)
+3 -13
View File
@@ -1,29 +1,19 @@
use std::process::Child;
use std::time::Instant; use std::time::Instant;
use crate::timer::{TimerStart, TimerStop};
use crate::util::units::Second; use crate::util::units::Second;
pub struct WallClockTimer { pub struct WallClockTimer {
start: Instant, start: Instant,
} }
impl TimerStart for WallClockTimer { impl WallClockTimer {
fn start() -> WallClockTimer { pub fn start() -> WallClockTimer {
WallClockTimer { WallClockTimer {
start: Instant::now(), start: Instant::now(),
} }
} }
fn start_for_process(_: &Child) -> Self { pub fn stop(&self) -> Second {
Self::start()
}
}
impl TimerStop for WallClockTimer {
type Result = Second;
fn stop(&self) -> Second {
let duration = self.start.elapsed(); let duration = self.start.elapsed();
duration.as_secs() as f64 + f64::from(duration.subsec_nanos()) * 1e-9 duration.as_secs() as f64 + f64::from(duration.subsec_nanos()) * 1e-9
} }
+6 -18
View File
@@ -7,35 +7,23 @@ use std::process::Child;
use winapi::um::processthreadsapi::GetProcessTimes; use winapi::um::processthreadsapi::GetProcessTimes;
use winapi::um::winnt::HANDLE; use winapi::um::winnt::HANDLE;
use crate::timer::{CPUTimes, TimerStart, TimerStop}; use crate::timer::CPUTimes;
use crate::util::units::Second; use crate::util::units::Second;
const HUNDRED_NS_PER_MS: i64 = 10; const HUNDRED_NS_PER_MS: i64 = 10;
pub fn get_cpu_timer(process: &Child) -> Box<dyn TimerStop<Result = (Second, Second)>> { pub struct CPUTimer {
Box::new(CPUTimer::start_for_process(process))
}
struct CPUTimer {
handle: RawHandle, handle: RawHandle,
} }
impl TimerStart for CPUTimer { impl CPUTimer {
fn start() -> Self { pub fn start_for_process(process: &Child) -> Self {
panic!()
}
fn start_for_process(process: &Child) -> Self {
CPUTimer { CPUTimer {
handle: process.as_raw_handle(), handle: process.as_raw_handle(),
} }
} }
}
impl TimerStop for CPUTimer { pub fn stop(&self) -> (Second, Second) {
type Result = (Second, Second);
fn stop(&self) -> Self::Result {
let times = get_cpu_times(self.handle); let times = get_cpu_times(self.handle);
( (
times.user_usec as f64 * 1e-6, times.user_usec as f64 * 1e-6,
@@ -62,7 +50,7 @@ fn get_cpu_times(handle: RawHandle) -> 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 // 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 { if res != 0 {
// Extract times as laid out here: https://support.microsoft.com/en-us/help/188768/info-working-with-the-filetime-structure // 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. // Both user_time and kernel_time are spans that the process spent in either.
let user: i64 = (((user_time.dwHighDateTime as i64) << 32) let user: i64 = (((user_time.dwHighDateTime as i64) << 32)
+ user_time.dwLowDateTime as i64) + user_time.dwLowDateTime as i64)
/ HUNDRED_NS_PER_MS; / HUNDRED_NS_PER_MS;