#[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;
pub use platform::{cpu_time, ThreadId};
pub use std::io::Result;
use std::{
io, mem,
time::{Duration, Instant},
};
pub fn processor_numbers() -> std::io::Result<usize> {
std::thread::available_parallelism().map(|x| x.get())
}
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 old_time = mem::replace(&mut self.cpu_time, platform::cpu_time()?);
let old_now = mem::replace(&mut self.now, Instant::now());
let real_time = self.now.saturating_duration_since(old_now).as_secs_f64();
let cpu_time = self.cpu_time.saturating_sub(old_time).as_secs_f64();
Ok(cpu_time / real_time)
}
}
pub struct ThreadStat {
stat: platform::ThreadStat,
}
impl ThreadStat {
pub fn cur() -> Result<Self> {
Ok(ThreadStat {
stat: platform::ThreadStat::cur()?,
})
}
pub fn build(thread_id: ThreadId) -> Result<Self> {
Ok(ThreadStat {
stat: platform::ThreadStat::build(thread_id)?,
})
}
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 = 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);
let mut x = 1_000_000u64;
std::hint::black_box(&mut x);
let mut times = 1000u64;
std::hint::black_box(&mut times);
for i in 0..times {
let x = (0..x + i).into_iter().sum::<u64>();
std::hint::black_box(x);
}
let usage = stat.cpu().unwrap();
assert!(usage > 0.5)
}
}