Skip to content

Commit

Permalink
feat: ram power & limit samples count in pipe command
Browse files Browse the repository at this point in the history
  • Loading branch information
vladkens committed Dec 17, 2024
1 parent ef1b90e commit cf32394
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 10 deletions.
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
- uses: softprops/action-gh-release@v2
with:
files: macmon-${{ github.ref_name }}.tar.gz
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "macmon"
version = "0.4.1"
version = "0.4.2"
edition = "2021"

[lints.rust]
Expand Down
47 changes: 46 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ sudo cp target/release/macmon /usr/local/bin
Usage: macmon [OPTIONS] [COMMAND]

Commands:
raw Print metrics in JSON format – can be used for piping
pipe Output metrics in JSON format
debug Print debug information
help Print this message or the help of the given subcommand(s)

Expand All @@ -82,6 +82,51 @@ Controls:
q - quit
```

## Piping

You can use the pipe subcommand to output metrics in JSON format, which is suitable for piping into other tools or scripts. For example:

```sh
macmon pipe | jq
```

This command runs `macmon` in "pipe" mode and navigate output to `jq` for pretty-printing.

You can also specify the number of samples to run using `-s` or `--samples` parameter (default: `0`, which runs indefinitely), and set update interval in milliseconds using the `-i` or `--interval` parameter (default: `1000` ms). For example:

```sh
macmon pipe -s 10 -i 500 | jq
```

This will collect 10 samples with an update interval of 500 milliseconds.

### Output

```json
{
"temp": {
"cpu_temp_avg": 43.73614, // Celsius
"gpu_temp_avg": 36.95167 // Celsius
},
"memory": {
"ram_total": 25769803776, // Bytes
"ram_usage": 20985479168, // Bytes
"swap_total": 4294967296, // Bytes
"swap_usage": 2602434560 // Bytes
},
"ecpu_usage": [1181, 0.082656614], // (Frequency MHz, Usage %)
"pcpu_usage": [1974, 0.015181795], // (Frequency MHz, Usage %)
"gpu_usage": [461, 0.021497859], // (Frequency MHz, Usage %)
"cpu_power": 0.20486385, // Watts
"gpu_power": 0.017451683, // Watts
"ane_power": 0.0, // Watts
"all_power": 0.22231553, // Watts
"sys_power": 5.876533, // Watts
"ram_power": 0.11635789, // Watts
"gpu_ram_power": 0.0009615385 // Watts
}
```

## 🤝 Contributing
We love contributions! Whether you have ideas, suggestions, or bug reports, feel free to open an issue or submit a pull request. Your input is essential in helping us improve `macmon` 💪

Expand Down
17 changes: 14 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@ use std::error::Error;

#[derive(Debug, Subcommand)]
enum Commands {
/// Print metrics in JSON format – can be used for piping
Raw,
/// Output metrics in JSON format (suitable for piping)
#[command(alias = "raw")]
Pipe {
/// Number of samples to run for. Set to 0 to run indefinitely
#[arg(short, long, default_value_t = 0)]
samples: u32,
},

/// Print debug information
Debug,
Expand All @@ -36,13 +41,19 @@ fn main() -> Result<(), Box<dyn Error>> {
let msec = args.interval.max(100);

match &args.command {
Some(Commands::Raw) => {
Some(Commands::Pipe { samples }) => {
let mut sampler = Sampler::new()?;
let mut counter = 0u32;

loop {
let doc = sampler.get_metrics(msec)?;
let doc = serde_json::to_string(&doc)?;
println!("{}", doc);

counter += 1;
if *samples > 0 && counter >= *samples {
break;
}
}
}
Some(Commands::Debug) => debug::print_debug()?,
Expand Down
14 changes: 10 additions & 4 deletions src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pub struct Metrics {
pub ane_power: f32, // Watts
pub all_power: f32, // Watts
pub sys_power: f32, // Watts
pub ram_power: f32, // Watts
pub gpu_ram_power: f32, // Watts
}

// MARK: Helpers
Expand Down Expand Up @@ -220,7 +222,7 @@ impl Sampler {

// 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) {
for (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();
Expand All @@ -247,9 +249,11 @@ impl Sampler {

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)?,
"CPU Energy" => rs.cpu_power += cfio_watts(x.item, &x.unit, dt)?,
"GPU Energy" => rs.gpu_power += cfio_watts(x.item, &x.unit, dt)?,
c if c.starts_with("ANE") => rs.ane_power += cfio_watts(x.item, &x.unit, dt)?,
c if c.starts_with("DRAM") => rs.ram_power += cfio_watts(x.item, &x.unit, dt)?,
c if c.starts_with("GPU SRAM") => rs.gpu_ram_power += cfio_watts(x.item, &x.unit, dt)?,
_ => {}
}
}
Expand All @@ -270,6 +274,8 @@ impl Sampler {
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.ram_power = zero_div(results.iter().map(|x| x.ram_power).sum(), measures as _);
rs.gpu_ram_power = zero_div(results.iter().map(|x| x.gpu_ram_power).sum(), measures as _);
rs.all_power = rs.cpu_power + rs.gpu_power + rs.ane_power;

rs.memory = self.get_mem()?;
Expand Down

0 comments on commit cf32394

Please sign in to comment.