Skip to content

Commit

Permalink
add debug print
Browse files Browse the repository at this point in the history
  • Loading branch information
vladkens committed Jun 25, 2024
1 parent 2dc8767 commit 18d1ad8
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 12 deletions.
103 changes: 103 additions & 0 deletions src/debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use core_foundation::base::CFRelease;

use crate::sources::{
cfdict_keys, cfio_get_props, get_dvfs_mhz, IOHIDSensors, IOReport, IOServiceIterator, SMC,
};

type WithError<T> = Result<T, Box<dyn std::error::Error>>;

fn divider(msg: &str) {
if msg.len() == 0 {
println!("{}", "-".repeat(80));
return;
}

let len = 80 - msg.len() - 2 - 3;
println!("\n--- {} {}", msg, "-".repeat(len));
}

pub fn print_debug() -> WithError<()> {
// system_profiler -listDataTypes
let out = std::process::Command::new("system_profiler")
.args(&["SPHardwareDataType", "SPDisplaysDataType", "-json"])
.output()
.unwrap();

let out = std::str::from_utf8(&out.stdout).unwrap();
let out = serde_json::from_str::<serde_json::Value>(out).unwrap();

let mac_model = out["SPHardwareDataType"][0]["machine_model"].as_str().unwrap().to_string();
let chip_name = out["SPHardwareDataType"][0]["chip_type"].as_str().unwrap().to_string();
println!("{} :: {}", chip_name, mac_model);

divider("AppleARMIODevice");
for (entry, name) in IOServiceIterator::new("AppleARMIODevice")? {
if name == "pmgr" {
let item = cfio_get_props(entry, name)?;
let mut keys = cfdict_keys(item);
keys.sort();

for key in keys {
if !key.contains("voltage-states") {
continue;
}

let (volts, freqs) = get_dvfs_mhz(item, &key);
let volts = volts.iter().map(|x| x.to_string()).collect::<Vec<String>>().join(" ");
let freqs = freqs.iter().map(|x| x.to_string()).collect::<Vec<String>>().join(" ");
println!("{:>32}: (v) {}", key, volts);
println!("{:>32}: (f) {}", key, freqs);
}

unsafe { CFRelease(item as _) }
}
}

divider("IOReport");
let channels = vec![
// ("Energy Model", None),
("CPU Stats", Some("CPU Complex Performance States")),
("CPU Stats", Some("CPU Core Performance States")),
("GPU Stats", Some("GPU Performance States")),
];

let ior = IOReport::new(channels)?;
for x in ior.get_sample(100) {
println!("{} :: {} :: {} ({})", x.group, x.subgroup, x.channel, x.unit);
// println!("{:?}", x);
}

divider("IOHID");
let hid = IOHIDSensors::new()?;
for (key, val) in hid.get_metrics() {
println!("{:>32}: {:6.2}", key, val);
}

divider("SMC");
let mut smc = SMC::new()?;
let keys = smc.read_all_keys().unwrap_or(vec![]);
for key in &keys {
let ki = smc.read_key_info(&key)?;
if ki.data_size != 4 || ki.data_type != 1718383648 {
continue;
}

let val = smc.read_val(&key);
if val.is_err() {
continue;
}

let val = val.unwrap();
let val = f32::from_le_bytes(val.data.clone().try_into().unwrap());
if val < 10.0 || val > 120.0 {
continue;
}

print!("{}={:.2} ", key, val);
}

println!();
divider("");

Ok(())
}
8 changes: 3 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod app;
pub mod debug;
pub mod metrics;
pub mod sources;

Expand All @@ -12,7 +13,7 @@ enum Commands {
/// Print raw metrics data instead of TUI
Raw,

/// Print diagnostic information (all possible metrics)
/// Print raw metrics data instead of TUI
Debug,
}

Expand All @@ -27,10 +28,6 @@ struct Cli {
/// Update interval in milliseconds
#[arg(short, long, default_value_t = 1000)]
interval: u64,

/// Print raw data instead of TUI
#[arg(long, default_value_t = false)]
raw: bool,
}

fn main() -> Result<(), Box<dyn Error>> {
Expand All @@ -46,6 +43,7 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("{:?}", metrics);
}
}
Some(Commands::Debug) => debug::print_debug()?,
_ => {
let mut app = App::new()?;
app.run_loop(msec)?;
Expand Down
7 changes: 3 additions & 4 deletions src/metrics.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use core_foundation::dictionary::CFDictionaryRef;

use crate::sources::{
cfio_get_residencies, cfio_watts, libc_ram_info, libc_swap_info, IOHIDSensors, IOReport, SocInfo,
SMC,
cfio_get_residencies, cfio_watts, libc_ram, libc_swap, IOHIDSensors, IOReport, SocInfo, SMC,
};

type WithError<T> = Result<T, Box<dyn std::error::Error>>;
Expand Down Expand Up @@ -200,8 +199,8 @@ impl Sampler {
}

fn get_mem(&mut self) -> WithError<MemMetrics> {
let (ram_usage, ram_total) = libc_ram_info()?;
let (swap_usage, swap_total) = libc_swap_info()?;
let (ram_usage, ram_total) = libc_ram()?;
let (swap_usage, swap_total) = libc_swap()?;
Ok(MemMetrics { ram_total, ram_usage, swap_total, swap_usage })
}

Expand Down
13 changes: 10 additions & 3 deletions src/sources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ impl Iterator for IOReportIterator {

// MARK: RAM

pub fn libc_ram_info() -> WithError<(u64, u64)> {
pub fn libc_ram() -> WithError<(u64, u64)> {
let (mut usage, mut total) = (0u64, 0u64);

unsafe {
Expand Down Expand Up @@ -339,7 +339,7 @@ pub fn libc_ram_info() -> WithError<(u64, u64)> {
Ok((usage, total))
}

pub fn libc_swap_info() -> WithError<(u64, u64)> {
pub fn libc_swap() -> WithError<(u64, u64)> {
let (mut usage, mut total) = (0u64, 0u64);

unsafe {
Expand Down Expand Up @@ -371,6 +371,7 @@ pub fn libc_swap_info() -> WithError<(u64, u64)> {

#[derive(Debug, Default, Clone)]
pub struct SocInfo {
pub mac_model: String,
pub chip_name: String,
pub memory_gb: u8,
pub ecpu_cores: u8,
Expand All @@ -388,7 +389,7 @@ impl SocInfo {
}

// dynamic voltage and frequency scaling
fn get_dvfs_mhz(dict: CFDictionaryRef, key: &str) -> (Vec<u32>, Vec<u32>) {
pub fn get_dvfs_mhz(dict: CFDictionaryRef, key: &str) -> (Vec<u32>, Vec<u32>) {
unsafe {
let obj = cfdict_get_val(dict, key).unwrap() as CFDataRef;
let obj_len = CFDataGetLength(obj);
Expand Down Expand Up @@ -423,6 +424,9 @@ pub fn get_soc_info() -> WithError<SocInfo> {
// SPHardwareDataType.0.chip_type
let chip_name = out["SPHardwareDataType"][0]["chip_type"].as_str().unwrap().to_string();

// SPHardwareDataType.0.machine_model
let mac_model = out["SPHardwareDataType"][0]["machine_model"].as_str().unwrap().to_string();

// SPHardwareDataType.0.physical_memory -> "x GB"
let mem_gb = out["SPHardwareDataType"][0]["physical_memory"].as_str();
let mem_gb = mem_gb.expect("No memory found").strip_suffix(" GB").unwrap();
Expand All @@ -441,6 +445,7 @@ pub fn get_soc_info() -> WithError<SocInfo> {
};

info.chip_name = chip_name;
info.mac_model = mac_model;
info.memory_gb = mem_gb as u8;
info.gpu_cores = gpu_cores as u8;
info.ecpu_cores = ecpu_cores as u8;
Expand All @@ -450,6 +455,8 @@ pub fn get_soc_info() -> WithError<SocInfo> {
for (entry, name) in IOServiceIterator::new("AppleARMIODevice")? {
if name == "pmgr" {
let item = cfio_get_props(entry, name)?;
// `strings /usr/bin/powermetrics | grep voltage-states` uses non sram keys
// but their values are zero, so sram used here, its looks valid
info.ecpu_freqs = get_dvfs_mhz(item, "voltage-states1-sram").1;
info.pcpu_freqs = get_dvfs_mhz(item, "voltage-states5-sram").1;
info.gpu_freqs = get_dvfs_mhz(item, "voltage-states9").1;
Expand Down

0 comments on commit 18d1ad8

Please sign in to comment.