2018-02-05 18:22:59 -05:00
|
|
|
#![cfg(windows)]
|
|
|
|
|
|
|
|
|
|
use std::mem;
|
2018-02-07 19:03:52 -05:00
|
|
|
use std::os::windows::io::{AsRawHandle, RawHandle};
|
|
|
|
|
use std::process::Child;
|
2018-02-05 18:22:59 -05:00
|
|
|
|
2021-08-24 21:33:48 +02:00
|
|
|
use winapi::um::processthreadsapi::GetProcessTimes;
|
|
|
|
|
use winapi::um::winnt::HANDLE;
|
|
|
|
|
|
2022-02-22 10:29:58 +01:00
|
|
|
use crate::timer::CPUTimes;
|
2022-02-06 20:01:41 +01:00
|
|
|
use crate::util::units::Second;
|
2021-08-24 21:33:48 +02:00
|
|
|
|
2018-02-05 18:22:59 -05:00
|
|
|
const HUNDRED_NS_PER_MS: i64 = 10;
|
|
|
|
|
|
2022-02-22 10:29:58 +01:00
|
|
|
pub struct CPUTimer {
|
2018-02-05 18:22:59 -05:00
|
|
|
handle: RawHandle,
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-22 10:29:58 +01:00
|
|
|
impl CPUTimer {
|
|
|
|
|
pub fn start_for_process(process: &Child) -> Self {
|
2018-03-22 21:53:36 -04:00
|
|
|
CPUTimer {
|
|
|
|
|
handle: process.as_raw_handle(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-02-07 19:03:52 -05:00
|
|
|
|
2022-02-22 10:29:58 +01:00
|
|
|
pub fn stop(&self) -> (Second, Second) {
|
2018-02-05 18:22:59 -05:00
|
|
|
let times = get_cpu_times(self.handle);
|
2018-03-22 21:53:36 -04:00
|
|
|
(
|
|
|
|
|
times.user_usec as f64 * 1e-6,
|
|
|
|
|
times.system_usec as f64 * 1e-6,
|
|
|
|
|
)
|
2018-02-05 18:22:59 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-22 10:08:15 +01:00
|
|
|
/// Read CPU execution times
|
2018-02-05 18:22:59 -05:00
|
|
|
fn get_cpu_times(handle: RawHandle) -> CPUTimes {
|
2022-07-21 22:47:40 +08:00
|
|
|
let (user_usec, system_usec) = {
|
|
|
|
|
let mut _ctime = unsafe { mem::zeroed() };
|
|
|
|
|
let mut _etime = unsafe { mem::zeroed() };
|
|
|
|
|
let mut kernel_time = unsafe { mem::zeroed() };
|
|
|
|
|
let mut user_time = unsafe { mem::zeroed() };
|
|
|
|
|
let res = unsafe {
|
|
|
|
|
GetProcessTimes(
|
|
|
|
|
handle as HANDLE,
|
|
|
|
|
&mut _ctime,
|
|
|
|
|
&mut _etime,
|
|
|
|
|
&mut kernel_time,
|
|
|
|
|
&mut user_time,
|
|
|
|
|
)
|
|
|
|
|
};
|
2018-02-05 18:22:59 -05:00
|
|
|
|
|
|
|
|
// 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
|
2022-02-22 10:29:58 +01:00
|
|
|
// Both user_time and kernel_time are spans that the process spent in either.
|
2018-03-22 21:53:36 -04:00
|
|
|
let user: i64 = (((user_time.dwHighDateTime as i64) << 32)
|
2019-10-02 18:56:55 +05:45
|
|
|
+ user_time.dwLowDateTime as i64)
|
|
|
|
|
/ HUNDRED_NS_PER_MS;
|
2018-03-22 21:53:36 -04:00
|
|
|
let kernel: i64 = (((kernel_time.dwHighDateTime as i64) << 32)
|
|
|
|
|
+ kernel_time.dwLowDateTime as i64)
|
|
|
|
|
/ HUNDRED_NS_PER_MS;
|
2018-02-05 18:22:59 -05:00
|
|
|
(user, kernel)
|
|
|
|
|
} else {
|
|
|
|
|
(0, 0)
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CPUTimes {
|
2018-03-22 21:53:36 -04:00
|
|
|
user_usec,
|
|
|
|
|
system_usec,
|
2018-02-05 18:22:59 -05:00
|
|
|
}
|
|
|
|
|
}
|