Skip to content

Commit

Permalink
Record gpu usage on macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaopengli89 committed Aug 13, 2021
1 parent e490110 commit 4b79095
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 7 deletions.
63 changes: 63 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Expand Up @@ -13,11 +13,16 @@ futures = "0.3.15"
futures-timer = "3.0.2"
plotters = "0.3"
clap = "3.0.0-beta.2"
plist = "1.2.1"

[dependencies.heim]
version = "0.1.0-rc.1"
features = ["process"]

[dependencies.serde]
version = "1.0.127"
features = ["serde_derive"]

[patch.crates-io.heim]
version = "0.1.0-rc.1"
git = "https://github.com/heim-rs/heim"
Expand Down
39 changes: 32 additions & 7 deletions src/main.rs
Expand Up @@ -5,11 +5,14 @@ use futures::stream::StreamExt;
use heim::process::{CpuUsage, Pid, Process, Status};
use heim::units::ratio;
use plotters::prelude::*;
use power_metrics::{PowerMetrics, PowerMetricsResult};
use std::io::BufReader;
use std::io::{BufRead, Write};
use std::process;
use std::time::{Duration, Instant};

mod power_metrics;

fn main() {
let opts: Opts = Opts::parse();

Expand All @@ -21,6 +24,7 @@ fn main() {
}

let mut powershell = None;
let power_metrics = PowerMetrics::new();

#[cfg(target_os = "windows")]
if opts.category.contains(&"gpu".to_owned()) {
Expand All @@ -40,6 +44,8 @@ fn main() {
last_record_time = now;
}

let power_metrics_result = power_metrics.poll();

'p: for process in processes.iter_mut() {
let mut message = format!("{}({})", &process.name, process.process.pid(),);

Expand All @@ -64,7 +70,8 @@ fn main() {
}
}
"gpu" => {
if let Some(gpu_percent) = process.poll_gpu_percent(powershell.as_mut())
if let Some(gpu_percent) =
process.poll_gpu_percent(powershell.as_mut(), &power_metrics_result)
{
process.value_percents[idx].push(gpu_percent);

Expand Down Expand Up @@ -244,13 +251,30 @@ impl ProcessInfo {
}
}

fn poll_gpu_percent(&mut self, powershell: Option<&mut Powershell>) -> Option<f32> {
let powershell = powershell?;
let r = powershell.poll_gpu_percent(self.process.pid());
if r.is_none() {
self.valid = false;
#[allow(unused_variables)]
fn poll_gpu_percent(
&mut self,
powershell: Option<&mut Powershell>,
power_metrics_result: &PowerMetricsResult,
) -> Option<f32> {
#[cfg(target_os = "windows")]
{
let powershell = powershell?;
let r = powershell.poll_gpu_percent(self.process.pid());
if r.is_none() {
self.valid = false;
}
r
}

#[cfg(not(target_os = "windows"))]
{
let r = power_metrics_result.gpu_percent(self.process.pid());
if r.is_none() {
self.valid = false;
}
r
}
r
}

fn avg_percent(&self, idx: usize) -> f32 {
Expand Down Expand Up @@ -283,6 +307,7 @@ impl Powershell {
}
}

#[allow(dead_code)]
fn poll_gpu_percent(&mut self, pid: Pid) -> Option<f32> {
let mut gpu_percent = 0.0;
let mut r = String::new();
Expand Down
52 changes: 52 additions & 0 deletions src/power_metrics.rs
@@ -0,0 +1,52 @@
use heim::process::Pid;
use serde::Deserialize;
use std::process::Command;

#[derive(Debug, Deserialize)]
pub struct PowerMetricsResult {
tasks: Vec<Task>,
}

impl PowerMetricsResult {
pub fn gpu_percent(&self, pid: Pid) -> Option<f32> {
self.tasks
.iter()
.find(|task| task.pid == pid)
.map(|task| task.gputime_ms_per_s / 10.0)
}
}

#[derive(Debug, Deserialize)]
pub struct Task {
pid: Pid,
#[serde(default)]
gputime_ms_per_s: f32,
}

pub struct PowerMetrics {}

impl PowerMetrics {
pub fn new() -> Self {
Self {}
}

pub fn poll(&self) -> PowerMetricsResult {
let o = Command::new("powermetrics")
.args([
"--samplers",
"tasks",
"--show-process-gpu",
"-n1",
"-i1000",
"-f",
"plist",
])
.output()
.unwrap();

assert_eq!(o.status.code(), Some(0));

let r: PowerMetricsResult = plist::from_bytes(o.stdout.as_slice()).unwrap();
r
}
}

0 comments on commit 4b79095

Please sign in to comment.