#[cfg(any(target_os = "linux", target_os = "android"))]
mod android_linux;
#[cfg(any(target_os = "ios", target_os = "macos"))]
mod ios_macos;
#[cfg(target_os = "windows")]
mod windows;
#[cfg(any(target_os = "linux", target_os = "android"))]
use android_linux as platform;
#[cfg(any(target_os = "ios", target_os = "macos"))]
use ios_macos as platform;
#[cfg(target_os = "windows")]
use windows as platform;
use std::{
io, mem,
time::{Duration, Instant},
};
pub use platform::{cpu_time, cur_thread_id, processor_numbers};
pub use std::io::Result;
pub struct ProcessStat {
now: Instant,
cpu_time: Duration,
}
impl ProcessStat {
pub fn cur() -> io::Result<Self> {
Ok(ProcessStat {
now: Instant::now(),
cpu_time: platform::cpu_time()?,
})
}
pub fn cpu(&mut self) -> io::Result<f64> {
let new_time = platform::cpu_time()?;
let old_time = mem::replace(&mut self.cpu_time, new_time);
let old_now = mem::replace(&mut self.now, Instant::now());
let real_time = self.now.duration_since(old_now).as_secs_f64();
if real_time > 0.0 {
let cpu_time = new_time
.checked_sub(old_time)
.map(|dur| dur.as_secs_f64())
.unwrap_or(0.0);
Ok(cpu_time / real_time)
} else {
Ok(0.0)
}
}
}
pub struct ThreadStat {
stat: platform::ThreadStat,
}
impl ThreadStat {
pub fn cur() -> Result<Self> {
Ok(ThreadStat {
stat: platform::ThreadStat::cur()?,
})
}
pub fn build(_pid: u32, tid: u32) -> Result<Self> {
Ok(ThreadStat {
#[cfg(any(target_os = "linux", target_os = "android"))]
stat: android_linux::ThreadStat::build(_pid, tid)?,
#[cfg(any(target_os = "ios", target_os = "macos", target_os = "windows"))]
stat: platform::ThreadStat::build(tid)?,
})
}
pub fn cpu(&mut self) -> Result<f64> {
self.stat.cpu()
}
pub fn cpu_time(&mut self) -> Result<Duration> {
self.stat.cpu_time()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
#[ignore]
fn test_process_usage() {
let mut stat = ProcessStat::cur().unwrap();
std::thread::sleep(std::time::Duration::from_secs(1));
let usage = stat.cpu().unwrap();
assert!(usage < 0.01);
let num = platform::processor_numbers().unwrap();
for _ in 0..num * 10 {
std::thread::spawn(move || loop {
let _ = (0..10_000_000).into_iter().sum::<u128>();
});
}
let mut stat = ProcessStat::cur().unwrap();
std::thread::sleep(std::time::Duration::from_secs(1));
let usage = stat.cpu().unwrap();
assert!(usage > 0.9 * num as f64)
}
#[test]
fn test_thread_usage() {
let mut stat = ThreadStat::cur().unwrap();
std::thread::sleep(std::time::Duration::from_secs(1));
let usage = stat.cpu().unwrap();
assert!(usage < 0.01);
for _ in 0..10 {
let _ = (0..1_000_000).into_iter().sum::<u128>();
}
let usage = stat.cpu().unwrap();
assert!(usage > 0.9)
}
}