monitoring kit
-rw-r--r--gpu/Cargo.toml9
-rw-r--r--gpu/src/intel.rs17
-rw-r--r--gpu/src/nvidia.rs113
-rw-r--r--grapher/src/lib.rs3
4 files changed, 132 insertions, 10 deletions
diff --git a/gpu/Cargo.toml b/gpu/Cargo.toml
index 6c9335e..c2c923d 100644
--- a/gpu/Cargo.toml
+++ b/gpu/Cargo.toml
@@ -16,9 +16,18 @@ parking_lot = "0.12.3"
termion = "4.0.4"
grapher = { path = "../grapher" }
memchr = "2.7.4"
+implicit-fn = "0.1.0"
+nvml-wrapper = "0.10.0"
+pretty-bytes = "0.2.2"
[[bin]]
name = "intel"
doc = false
path = "src/intel.rs"
+
+
+[[bin]]
+name = "nvidia"
+doc = false
+path = "src/nvidia.rs"
diff --git a/gpu/src/intel.rs b/gpu/src/intel.rs
index 1352fb0..f7cc2db 100644
--- a/gpu/src/intel.rs
+++ b/gpu/src/intel.rs
@@ -72,19 +72,20 @@ unsafe extern "C" {
fn igt_device_get_pretty_name(card: *const igt_device_card, numeric: bool) -> *const c_char;
}
+#[implicit_fn::implicit_fn]
fn uh() -> Result<()> {
dbg!("???");
let x = std::fs::read_dir("/sys/devices")?
.filter_map(Result::ok)
- .filter(|x| {
- x.file_name()
+ .filter(
+ _.file_name()
.into_string()
- .is_ok_and(|x| x.starts_with("pci"))
- })
+ .is_ok_and(|x| x.starts_with("pci")),
+ )
.filter_map(|x| read_dir(x.path()).ok())
.flatten()
.filter_map(Result::ok)
- .find(|x| read(x.path().join("uevent")).is_ok_and(|x| x.contains("i915")))
+ .find(|x| read(x.path().join("uevent")).is_ok_and(_.contains("nvidia")))
.ok_or(anyhow!("intelless"))?
.path();
@@ -145,10 +146,6 @@ fn main() -> Result<()> {
.unwrap()
};
- fn inter([a, b, c]: [f32; 3], [d, e, f]: [f32; 3], fc: f32) -> [f32; 3] {
- [a + (d - a) * fc, b + (e - b) * fc, c + (f - c) * fc]
- }
-
let mut g = Grapher::new()?;
sleep(Duration::from_secs_f32(0.5));
if let std::result::Result::Ok(Some(_)) = c.try_wait() {
@@ -176,7 +173,7 @@ fn main() -> Result<()> {
g.draw(
|y| {
Some(
- inter(
+ grapher::inter(
[243, 64, 64].map(|x| x as f32 / 255.0), // red
[228, 197, 63].map(|x| x as f32 / 255.0), // yellow
y as f32 / (h - 1) as f32,
diff --git a/gpu/src/nvidia.rs b/gpu/src/nvidia.rs
new file mode 100644
index 0000000..6b8be77
--- /dev/null
+++ b/gpu/src/nvidia.rs
@@ -0,0 +1,113 @@
+#![feature(
+ generic_arg_infer,
+ import_trait_associated_functions,
+ let_chains,
+ iter_array_chunks,
+ array_chunks,
+ portable_simd,
+ iter_chain
+)]
+use anyhow::*;
+use grapher::inter;
+use grapher::truncwrite;
+use grapher::Grapher;
+use nvml_wrapper::{
+ enum_wrappers::device::{Clock, TemperatureSensor},
+ Nvml,
+};
+use pretty_bytes::converter::convert;
+use std::array;
+use std::convert::identity;
+use std::io::Write;
+use std::io::{stdout, Read};
+use std::thread::sleep;
+use std::time::Duration;
+use termion::color::*;
+use termion::cursor::Hide;
+use termion::raw::IntoRawMode;
+use termion::screen::IntoAlternateScreen;
+use termion::{async_stdin, clear, cursor, style};
+#[implicit_fn::implicit_fn]
+fn main() -> Result<()> {
+ let vram = std::env::args().nth(1).is_some();
+ let nvml = Nvml::init().context("nvml(nvidia) less")?;
+ let device = nvml.device_by_index(0).context("nvidialess")?;
+ let name = device.name()?;
+ let name = name.replace("NVIDIA GeForce RTX", "RTX");
+
+ let architecture = device.architecture()?;
+ let mut g = Grapher::new()?;
+ let mut d = 0.1;
+ let mut stdout = stdout().into_raw_mode()?.into_alternate_screen()?;
+ let mut stdin = async_stdin();
+ write!(stdout, "{}{}{}", Hide, clear::All, style::Reset).unwrap();
+ 'out: loop {
+ let (_, h) = termion::terminal_size()?;
+
+ let mut key = 0;
+ while stdin.read(array::from_mut(&mut key)).unwrap() != 0 {
+ match key {
+ b'q' => break 'out,
+ b'+' => d = (d + 0.1f32).min(1.0),
+ b'-' if d >= 0.2 => d -= 0.1,
+ b'-' if d >= 0.02 => d -= 0.01,
+ b'-' => d = 0.00833,
+ _ => (),
+ }
+ }
+
+ g.draw(
+ |y| {
+ Some(
+ inter(
+ [155, 221, 58].map(_ as f32 / 255.0),
+ [118, 185, 0].map(_ as f32 / 255.0),
+ y as f32 / (h - 1) as f32,
+ )
+ .map(|x| (x * 255.0) as u8),
+ )
+ },
+ identity,
+ )?;
+
+ write!(g.buffer, "{}{}", White.fg_str(), cursor::Goto(1, 1))?;
+
+ let temperature = device.temperature(TemperatureSensor::Gpu)?;
+ let max = device.temperature_threshold(
+ nvml_wrapper::enum_wrappers::device::TemperatureThreshold::Slowdown,
+ )?;
+
+ let mem_info = device.memory_info()?;
+ let util = device.utilization_rates()?.gpu;
+
+ let graphics_clock = device.clock_info(Clock::Graphics)?;
+ let mem_clock = device.clock_info(Clock::Memory)?;
+ let usage = device.power_usage()? / 1000;
+ let of = device.power_management_limit()? / 1000;
+
+ let used_mem = convert(mem_info.used as _);
+ let total_mem = convert(mem_info.total as _);
+ if vram {
+ truncwrite!(
+ g.buffer,
+ "{name} {used_mem}/ {total_mem} vRAM speed {mem_clock} MHZ"
+ )?;
+ } else {
+ truncwrite!(g.buffer, "{name} ({architecture}) @ {temperature}°C (max {max}°C) {usage}W/ {of}W {util}% usage\n\r")?;
+ truncwrite!(g.buffer, "{graphics_clock} MHz mem {mem_clock} MHz\n\r")?;
+ truncwrite!(g.buffer, "{used_mem}/ {total_mem} vRAM\n\r")?;
+ }
+ stdout.write_all(&g.buffer)?;
+ stdout.flush()?;
+
+ sleep(Duration::from_secs_f32(d));
+ if vram {
+ g.push_point(mem_info.used as f64 / mem_info.total as f64);
+ } else {
+ g.push_point(util as f64 / 1e2);
+ }
+ }
+ println!("\x1B[?7l");
+
+ Ok(())
+}
diff --git a/grapher/src/lib.rs b/grapher/src/lib.rs
index 6f98eed..3b4592f 100644
--- a/grapher/src/lib.rs
+++ b/grapher/src/lib.rs
@@ -14,6 +14,9 @@ use std::simd::prelude::*;
use termion::color::*;
use termion::{clear, cursor};
use unicode_width::*;
+pub fn inter([a, b, c]: [f32; 3], [d, e, f]: [f32; 3], fc: f32) -> [f32; 3] {
+ [a + (d - a) * fc, b + (e - b) * fc, c + (f - c) * fc]
+}
pub struct Grapher {
pub buffer: Vec<u8>,