Skip to content

Commit

Permalink
Add usage
Browse files Browse the repository at this point in the history
  • Loading branch information
roblabla authored and svartalf committed Dec 11, 2020
1 parent 58d7110 commit 970dccc
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 0 deletions.
1 change: 1 addition & 0 deletions heim-cpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ heim-derive = { version = "0.1.0-beta.1", path = "../heim-derive" }
smol = "~1.2"
futures = "~0.3"
version-sync = "0.9"
futures-timer = "^3.0"

[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]
2 changes: 2 additions & 0 deletions heim-cpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ mod count;
mod freq;
mod stats;
mod times;
mod usage;

pub use self::count::*;
pub use self::freq::*;
pub use self::stats::*;
pub use self::times::*;
pub use self::usage::*;
89 changes: 89 additions & 0 deletions heim-cpu/src/usage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use std::ops;
use std::time::Instant;

use heim_common::prelude::*;
use heim_common::units::{ratio, time, Ratio};

use super::{logical_count, time, CpuTime};

/// System CPU usage measurement.
///
/// See [cpu_usage](./fn.cpu_usage.html) method for details.
#[derive(Debug, Clone)]
pub struct CpuUsage {
pub(crate) cpu_count: u64,
pub(crate) cpu_time: CpuTime,
pub(crate) at: Instant,
}

impl ops::Sub<CpuUsage> for CpuUsage {
type Output = Ratio;

#[allow(clippy::suspicious_arithmetic_impl, clippy::cast_lossless)]
fn sub(self, rhs: CpuUsage) -> Self::Output {
let delta_proc = (self.cpu_time.user() - rhs.cpu_time.user())
+ (self.cpu_time.system() - rhs.cpu_time.system());
let delta_time = self.at - rhs.at;

// TODO: Can be replaced with a `delta_time.as_secs_f64()`
// as soon as https://github.com/rust-lang/rust/issues/54361 will be stable
const NANOS_PER_SEC: u32 = 1_000_000_000;
let mut delta_time_secs =
(delta_time.as_secs() as f64) + (delta_time.as_nanos() as f64) / (NANOS_PER_SEC as f64);

// Time should calculated across all the cores available
delta_time_secs *= self.cpu_count as f64;

if delta_time_secs != 0.0 {
let overall_cpus_ratio = delta_proc.get::<time::second>() / delta_time_secs;
let single_cpu_ratio = overall_cpus_ratio * self.cpu_count as f64;

Ratio::new::<ratio::ratio>(single_cpu_ratio as f32)
} else {
Ratio::new::<ratio::ratio>(0.0)
}
}
}

/// Returns CPU usage measurement.
///
/// Returned [`CpuUsage`] struct represents instantaneous CPU usage and does not represent
/// any reasonable value by itself.
/// It is suggested to wait for a while with help of any async timer
/// (for accuracy recommended delay should be at least 100 ms),
/// call this method once again and subtract former [`CpuUsage`] from the new one.
///
/// Same to any *nix system, calculated CPU usage might exceed 100 %
/// if the process is running multiple threads on different CPU cores.
///
/// ## Example
///
/// ```rust
/// # use std::time::Duration;
/// # use heim_common::units::ratio;
/// # use heim_common::prelude::*;
/// # use heim_cpu::usage;
/// #
/// # #[heim_derive::main]
/// # async fn main() -> Result<()> {
/// let measurement_1 = usage().await?;
/// // Or any other async timer at your choice
/// futures_timer::Delay::new(Duration::from_millis(100)).await;
/// let measurement_2 = usage().await?;
///
/// println!("CPU usage: {} %", (measurement_2 - measurement_1).get::<ratio::percent>());
/// # Ok(())
/// # }
/// ```
///
/// [`CpuUsage`]: ./struct.CpuUsage.html
pub async fn usage() -> Result<CpuUsage> {
let (cpu_time, cpu_count) =
future::try_join(time(), logical_count().map_err(Into::into)).await?;

Ok(CpuUsage {
cpu_count,
cpu_time,
at: Instant::now(),
})
}
5 changes: 5 additions & 0 deletions heim-cpu/tests/smoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,8 @@ async fn smoke_cpu_physical_count() {
assert!(cpus < 1024); // Some sane value till we will have proper unittests
}
}

#[heim_derive::test]
async fn smoke_cpu_usage() {
let _measurement = cpu::usage().await.unwrap();
}

0 comments on commit 970dccc

Please sign in to comment.