workflow_perf_monitor/cpu/windows/
mod.rs1use super::processor_numbers;
2use super::windows::process_times::ProcessTimes;
3use super::windows::system_times::SystemTimes;
4use super::windows::thread_times::ThreadTimes;
5use std::io::Result;
6use std::time::Duration;
7use windows_sys::Win32::Foundation::FILETIME;
8use windows_sys::Win32::System::Threading::GetCurrentThreadId;
9
10pub mod process_times;
11pub mod system_times;
12pub mod thread_times;
13
14#[derive(Clone, Copy)]
15pub struct ThreadId(u32);
16
17impl ThreadId {
18 #[inline]
19 pub fn current() -> Self {
20 ThreadId(unsafe { GetCurrentThreadId() })
21 }
22}
23
24fn filetime_to_ns100(ft: &FILETIME) -> u64 {
26 ((ft.dwHighDateTime as u64) << 32) + ft.dwLowDateTime as u64
27}
28
29pub struct ThreadStat {
30 tid: ThreadId,
31 last_work_time: u64,
32 last_total_time: u64,
33}
34
35impl ThreadStat {
36 fn get_times(thread_id: ThreadId) -> Result<(u64, u64)> {
37 let system_times = SystemTimes::capture()?;
38 let thread_times = ThreadTimes::capture_with_thread_id(thread_id)?;
39
40 let work_time =
41 filetime_to_ns100(&thread_times.kernel) + filetime_to_ns100(&thread_times.user);
42 let total_time =
43 filetime_to_ns100(&system_times.kernel) + filetime_to_ns100(&system_times.user);
44 Ok((work_time, total_time))
45 }
46
47 pub fn cur() -> Result<Self> {
48 let tid = ThreadId::current();
49 let (work_time, total_time) = Self::get_times(tid)?;
50 Ok(ThreadStat {
51 tid,
52 last_work_time: work_time,
53 last_total_time: total_time,
54 })
55 }
56
57 pub fn build(tid: ThreadId) -> Result<Self> {
58 let (work_time, total_time) = Self::get_times(tid)?;
59 Ok(ThreadStat {
60 tid,
61 last_work_time: work_time,
62 last_total_time: total_time,
63 })
64 }
65
66 pub fn cpu(&mut self) -> Result<f64> {
67 let (work_time, total_time) = Self::get_times(self.tid)?;
68
69 let dt_total_time = total_time - self.last_total_time;
70 if dt_total_time == 0 {
71 return Ok(0.0);
72 }
73 let dt_work_time = work_time - self.last_work_time;
74
75 self.last_work_time = work_time;
76 self.last_total_time = total_time;
77
78 Ok(dt_work_time as f64 / dt_total_time as f64 * processor_numbers()? as f64)
79 }
80
81 pub fn cpu_time(&mut self) -> Result<Duration> {
82 let (work_time, total_time) = Self::get_times(self.tid)?;
83
84 let cpu_time = work_time - self.last_work_time;
85
86 self.last_work_time = work_time;
87 self.last_total_time = total_time;
88
89 Ok(Duration::from_nanos(cpu_time))
90 }
91}
92
93#[inline]
94pub fn cpu_time() -> Result<Duration> {
95 let process_times = ProcessTimes::capture_current()?;
96
97 let kt = filetime_to_ns100(&process_times.kernel);
98 let ut = filetime_to_ns100(&process_times.user);
99
100 let cpu = (kt + ut).saturating_mul(100);
105
106 let cpu = cpu * processor_numbers()? as u64;
108
109 Ok(Duration::from_nanos(cpu))
110}