Skip to content

Commit

Permalink
better metrics interpolation #10
Browse files Browse the repository at this point in the history
  • Loading branch information
vladkens committed Nov 17, 2024
1 parent c1955f7 commit 7bfdaf4
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 52 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.DS_Store
/target
/internal
__handlers__/
13 changes: 6 additions & 7 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ fn run_inputs_thread(tx: mpsc::Sender<Event>, tick: u64) {
let mut last_tick = Instant::now();

loop {
if event::poll(Duration::from_millis(100)).unwrap() {
if event::poll(Duration::from_millis(tick)).unwrap() {
match event::read().unwrap() {
event::Event::Key(key) => handle_key_event(&key, &tx).unwrap(),
_ => {}
Expand All @@ -158,15 +158,15 @@ fn run_inputs_thread(tx: mpsc::Sender<Event>, tick: u64) {

fn run_sampler_thread(tx: mpsc::Sender<Event>, interval: u64) {
let interval = interval.max(100).min(10000);
let sample_duration = 80;

std::thread::spawn(move || {
let mut sampler = Sampler::new().unwrap();

// Send initial metrics
tx.send(Event::Update(sampler.get_metrics(100).unwrap())).unwrap();

loop {
let metrics = sampler.get_metrics(sample_duration).unwrap();
tx.send(Event::Update(metrics)).unwrap();
std::thread::sleep(Duration::from_millis(interval - sample_duration));
tx.send(Event::Update(sampler.get_metrics(interval).unwrap())).unwrap();
}
});
}
Expand Down Expand Up @@ -346,7 +346,6 @@ impl App {
self.render_freq_block(f, c2, "GPU", &self.igpu_freq);

// 3rd row

let label_l = format!(
"Power: {:.2}W (avg {:.2}W, max {:.2}W)",
self.all_power.top_value, self.all_power.avg_value, self.all_power.max_value,
Expand Down Expand Up @@ -380,7 +379,7 @@ impl App {

pub fn run_loop(&mut self, interval: u64) -> WithError<()> {
let (tx, rx) = mpsc::channel::<Event>();
run_inputs_thread(tx.clone(), 200);
run_inputs_thread(tx.clone(), 250);
run_sampler_thread(tx.clone(), interval);

let mut term = enter_term();
Expand Down
3 changes: 1 addition & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let mut sampler = Sampler::new()?;

loop {
let metrics = sampler.get_metrics(msec)?;
println!("{:?}", metrics);
println!("{:?}", sampler.get_metrics(msec)?);
}
}
Some(Commands::Debug) => debug::print_debug()?,
Expand Down
89 changes: 47 additions & 42 deletions src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,58 +214,63 @@ impl Sampler {
}

pub fn get_metrics(&mut self, duration: u64) -> WithError<Metrics> {
let mut rs = Metrics::default();

let mut ecpu_usages = Vec::new();
let mut pcpu_usages = Vec::new();

for x in self.ior.get_sample(duration) {
// if x.group == "CPU Stats" && x.subgroup == CPU_FREQ_DICE_SUBG {
// match x.channel.as_str() {
// "ECPU" => rs.ecpu_usage = calc_freq(x.item, &self.soc.ecpu_freqs),
// "PCPU" => rs.pcpu_usage = calc_freq(x.item, &self.soc.pcpu_freqs),
// _ => {}
// }
// }

if x.group == "CPU Stats" && x.subgroup == CPU_FREQ_CORE_SUBG {
if x.channel.contains("ECPU") {
ecpu_usages.push(calc_freq(x.item, &self.soc.ecpu_freqs));
continue;
let measures: usize = 4;
let mut results: Vec<Metrics> = Vec::with_capacity(measures);

// do several samples to smooth metrics
// see: https://github.com/vladkens/macmon/issues/10
for (sample, sample_dt) in self.ior.get_samples(duration, measures) {
let mut ecpu_usages = Vec::new();
let mut pcpu_usages = Vec::new();
let mut rs = Metrics::default();

for x in sample {
if x.group == "CPU Stats" && x.subgroup == CPU_FREQ_CORE_SUBG {
if x.channel.contains("ECPU") {
ecpu_usages.push(calc_freq(x.item, &self.soc.ecpu_freqs));
continue;
}

if x.channel.contains("PCPU") {
pcpu_usages.push(calc_freq(x.item, &self.soc.pcpu_freqs));
continue;
}
}

if x.channel.contains("PCPU") {
pcpu_usages.push(calc_freq(x.item, &self.soc.pcpu_freqs));
continue;
if x.group == "GPU Stats" && x.subgroup == GPU_FREQ_DICE_SUBG {
match x.channel.as_str() {
"GPUPH" => rs.gpu_usage = calc_freq(x.item, &self.soc.gpu_freqs[1..].to_vec()),
_ => {}
}
}
}

if x.group == "GPU Stats" && x.subgroup == GPU_FREQ_DICE_SUBG {
match x.channel.as_str() {
"GPUPH" => rs.gpu_usage = calc_freq(x.item, &self.soc.gpu_freqs[1..].to_vec()),
_ => {}
if x.group == "Energy Model" {
match x.channel.as_str() {
"CPU Energy" => rs.cpu_power += cfio_watts(x.item, &x.unit, sample_dt)?,
"GPU Energy" => rs.gpu_power += cfio_watts(x.item, &x.unit, sample_dt)?,
c if c.starts_with("ANE") => rs.ane_power += cfio_watts(x.item, &x.unit, sample_dt)?,
_ => {}
}
}
}

if x.group == "Energy Model" {
match x.channel.as_str() {
"CPU Energy" => rs.cpu_power += cfio_watts(x.item, &x.unit, duration)?,
"GPU Energy" => rs.gpu_power += cfio_watts(x.item, &x.unit, duration)?,
c if c.starts_with("ANE") => rs.ane_power += cfio_watts(x.item, &x.unit, duration)?,
_ => {}
}
}
rs.ecpu_usage = calc_freq_final(&ecpu_usages, &self.soc.ecpu_freqs);
rs.pcpu_usage = calc_freq_final(&pcpu_usages, &self.soc.pcpu_freqs);
results.push(rs);
}

// println!("----------");
// println!("{:?}", ecpu_usages);
// println!("{:?}", pcpu_usages);
// println!("1 {:?} {:?}", rs.ecpu_usage, rs.pcpu_usage);
rs.ecpu_usage = calc_freq_final(&ecpu_usages, &self.soc.ecpu_freqs);
rs.pcpu_usage = calc_freq_final(&pcpu_usages, &self.soc.pcpu_freqs);
// println!("2 {:?} {:?}", rs.ecpu_usage, rs.pcpu_usage);

let mut rs = Metrics::default();
rs.ecpu_usage.0 = zero_div(results.iter().map(|x| x.ecpu_usage.0).sum(), measures as _);
rs.ecpu_usage.1 = zero_div(results.iter().map(|x| x.ecpu_usage.1).sum(), measures as _);
rs.pcpu_usage.0 = zero_div(results.iter().map(|x| x.pcpu_usage.0).sum(), measures as _);
rs.pcpu_usage.1 = zero_div(results.iter().map(|x| x.pcpu_usage.1).sum(), measures as _);
rs.gpu_usage.0 = zero_div(results.iter().map(|x| x.gpu_usage.0).sum(), measures as _);
rs.gpu_usage.1 = zero_div(results.iter().map(|x| x.gpu_usage.1).sum(), measures as _);
rs.cpu_power = zero_div(results.iter().map(|x| x.cpu_power).sum(), measures as _);
rs.gpu_power = zero_div(results.iter().map(|x| x.gpu_power).sum(), measures as _);
rs.ane_power = zero_div(results.iter().map(|x| x.ane_power).sum(), measures as _);
rs.all_power = rs.cpu_power + rs.gpu_power + rs.ane_power;

rs.memory = self.get_mem()?;
rs.temp = self.get_temp()?;

Expand Down
37 changes: 36 additions & 1 deletion src/sources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,14 +532,15 @@ unsafe fn cfio_get_subs(chan: CFMutableDictionaryRef) -> WithError<IOReportSubsc
pub struct IOReport {
subs: IOReportSubscriptionRef,
chan: CFMutableDictionaryRef,
prev: Option<(CFDictionaryRef, std::time::Instant)>,
}

impl IOReport {
pub fn new(channels: Vec<(&str, Option<&str>)>) -> WithError<Self> {
let chan = unsafe { cfio_get_chan(channels)? };
let subs = unsafe { cfio_get_subs(chan)? };

Ok(Self { subs, chan })
Ok(Self { subs, chan, prev: None })
}

pub fn get_sample(&self, duration: u64) -> IOReportIterator {
Expand All @@ -554,13 +555,47 @@ impl IOReport {
IOReportIterator::new(sample3)
}
}

fn raw_sample(&self) -> (CFDictionaryRef, std::time::Instant) {
(unsafe { IOReportCreateSamples(self.subs, self.chan, null()) }, std::time::Instant::now())
}

pub fn get_samples(&mut self, duration: u64, count: usize) -> Vec<(IOReportIterator, u64)> {
let count = count.max(1).min(32);
let mut samples: Vec<(IOReportIterator, u64)> = Vec::with_capacity(count);
let step_msec = duration / count as u64;

let mut prev = match self.prev {
Some(x) => x,
None => self.raw_sample(),
};

for _ in 0..count {
std::thread::sleep(std::time::Duration::from_millis(step_msec));

let next = self.raw_sample();
let diff = unsafe { IOReportCreateSamplesDelta(prev.0, next.0, null()) };
unsafe { CFRelease(prev.0 as _) };

let elapsed = next.1.duration_since(prev.1).as_millis() as u64;
prev = next;

samples.push((IOReportIterator::new(diff), elapsed.max(1)));
}

self.prev = Some(prev);
samples
}
}

impl Drop for IOReport {
fn drop(&mut self) {
unsafe {
CFRelease(self.chan as _);
CFRelease(self.subs as _);
if self.prev.is_some() {
CFRelease(self.prev.unwrap().0 as _);
}
}
}
}
Expand Down

0 comments on commit 7bfdaf4

Please sign in to comment.