monitoring kit
bendn 11 months ago
parent 00c6249 · commit ffc3c10
-rw-r--r--cpu/Cargo.toml11
-rw-r--r--cpu/src/cpu.rs94
-rw-r--r--cpu/src/lib.rs (renamed from cpu/src/main.rs)110
-rw-r--r--cpu/src/temps.rs87
4 files changed, 206 insertions, 96 deletions
diff --git a/cpu/Cargo.toml b/cpu/Cargo.toml
index 66745ff..9fca4ee 100644
--- a/cpu/Cargo.toml
+++ b/cpu/Cargo.toml
@@ -16,3 +16,14 @@ parking_lot = "0.12.3"
regex = "1.11.1"
termion = "4.0.4"
grapher = { path = "../grapher" }
+
+
+[[bin]]
+name = "cpu"
+doc = false
+path = "src/cpu.rs"
+
+[[bin]]
+name = "temps"
+doc = false
+path = "src/temps.rs"
diff --git a/cpu/src/cpu.rs b/cpu/src/cpu.rs
new file mode 100644
index 0000000..459eef3
--- /dev/null
+++ b/cpu/src/cpu.rs
@@ -0,0 +1,94 @@
+#![feature(
+ let_chains,
+ iter_array_chunks,
+ array_chunks,
+ generic_const_exprs,
+ portable_simd,
+ iter_chain
+)]
+use anyhow::*;
+use comat::cwrite;
+use cpu::*;
+use grapher::Grapher;
+use std::array;
+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};
+
+fn main() -> Result<()> {
+ 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 info = CpuInfo::read()?;
+ let core = std::env::args()
+ .nth(1)
+ .and_then(|x| x.parse::<u64>().ok())
+ .map_or(ViewCore::All(info.count), ViewCore::One);
+ CORE.set(core).unwrap();
+ match core {
+ ViewCore::One(x) => ensure!(x < info.count, "not enough cores"),
+ _ => (),
+ }
+ let mut t = Temps::load()?;
+
+ let mut g = Grapher::new()?;
+ g.push_point(usage()?.max(0.01));
+
+ 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(
+ [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,
+ )
+ .map(|x| (x * 255.0) as u8),
+ )
+ })?;
+
+ write!(g.buffer, "{}{}", White.fg_str(), cursor::Goto(1, 1))?;
+ let name = &*info.name;
+ let speed = speed()?;
+ let temp = t.read()?;
+ let fps = (1f32 / d).round();
+ cwrite!(
+ g.buffer,
+ " {fps}fps ──── {name} {core} @ {speed:.2} GHz ──── {red}{temp}{reset} °C",
+ )?;
+ stdout.write_all(&g.buffer)?;
+ stdout.flush()?;
+
+ g.push_point(usage()?.max(0.01));
+
+ sleep(Duration::from_secs_f32(d));
+ }
+ println!("\x1B[?7l");
+ Ok(())
+}
diff --git a/cpu/src/main.rs b/cpu/src/lib.rs
index 9973dc6..5ddb34c 100644
--- a/cpu/src/main.rs
+++ b/cpu/src/lib.rs
@@ -6,31 +6,21 @@
portable_simd,
iter_chain
)]
-use anyhow::{anyhow, bail, ensure, Context, Result};
+use anyhow::*;
use atools::prelude::*;
use collar::CollectArray;
-use comat::cwrite;
-use grapher::Grapher;
use parking_lot::Mutex;
-use std::array;
use std::collections::HashMap;
use std::fmt::Display;
use std::fs::{read_to_string as read, File};
-use std::io::{stdout, Read};
-use std::io::{Seek, Write};
+use std::io::Read;
+use std::io::Seek;
use std::mem::replace;
use std::path::Path;
use std::sync::OnceLock;
-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};
#[derive(Copy, Clone, Debug)]
-enum ViewCore {
+pub enum ViewCore {
All(u64),
One(u64),
}
@@ -43,7 +33,7 @@ impl Display for ViewCore {
}
}
-static CORE: OnceLock<ViewCore> = OnceLock::new();
+pub static CORE: OnceLock<ViewCore> = OnceLock::new();
#[derive(Debug, Clone, Default, PartialEq)]
pub struct CpuInfo {
@@ -52,9 +42,9 @@ pub struct CpuInfo {
pub count: u64,
}
-struct Temps(File);
+pub struct Temps(File);
impl Temps {
- fn load() -> Result<Self> {
+ pub fn load() -> Result<Self> {
for hwmon in std::fs::read_dir("/sys/class/hwmon/")?.filter_map(Result::ok) {
if !read(Path::join(&hwmon.path(), "name"))?.starts_with("coretemp") {
continue;
@@ -86,16 +76,16 @@ impl Temps {
}
bail!("h")
}
- fn read(&mut self) -> Result<f32> {
+ pub fn read(&mut self) -> Result<f64> {
let mut o = String::default();
self.0.seek(std::io::SeekFrom::Start(0))?;
self.0.read_to_string(&mut o)?;
- Ok(o.trim().parse::<f32>().context("reading temps")? / 1000.0)
+ Ok(o.trim().parse::<f64>().context("reading temps")? / 1000.0)
}
}
impl CpuInfo {
- fn read() -> Result<Self> {
+ pub fn read() -> Result<Self> {
let x = String::from_utf8(
std::process::Command::new("lscpu")
.env("LC_ALL", "C")
@@ -131,7 +121,7 @@ impl CpuInfo {
}
}
-fn sped(core: u64) -> Result<f64> {
+pub fn sped(core: u64) -> Result<f64> {
Ok(read(format!(
"/sys/devices/system/cpu/cpu{core}/cpufreq/scaling_cur_freq"
))
@@ -142,21 +132,21 @@ fn sped(core: u64) -> Result<f64> {
/ 1e6)
}
-fn speed() -> Result<f64> {
+pub fn speed() -> Result<f64> {
Ok(match *CORE.get().unwrap() {
ViewCore::All(x) => (0..x).map(sped).sum::<Result<f64, _>>()? / x as f64,
ViewCore::One(x) => sped(x)?,
})
}
-fn core() -> Option<u64> {
+pub fn core() -> Option<u64> {
CORE.get().copied().and_then(|x| match x {
ViewCore::One(x) => Some(x),
_ => None,
})
}
-fn usage() -> Result<f64> {
+pub fn usage() -> Result<f64> {
let x = read("/proc/stat")?;
let x = x
.lines()
@@ -181,75 +171,3 @@ fn usage() -> Result<f64> {
let r = (tot - idle) / tot;
Ok((r == r).then_some(r).unwrap_or(0.0))
}
-
-fn main() -> Result<()> {
- 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 info = CpuInfo::read()?;
- let core = std::env::args()
- .nth(1)
- .and_then(|x| x.parse::<u64>().ok())
- .map_or(ViewCore::All(info.count), ViewCore::One);
- CORE.set(core).unwrap();
- match core {
- ViewCore::One(x) => ensure!(x < info.count, "not enough cores"),
- _ => (),
- }
- let mut t = Temps::load()?;
-
- let mut g = Grapher::new()?;
- g.push_point(usage()?.max(0.01));
-
- 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(
- [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,
- )
- .map(|x| (x * 255.0) as u8),
- )
- })?;
-
- write!(g.buffer, "{}{}", White.fg_str(), cursor::Goto(1, 1))?;
- let name = &*info.name;
- let speed = speed()?;
- let temp = t.read()?;
- let fps = (1f32 / d).round();
- cwrite!(
- g.buffer,
- " {fps}fps ──── {name} {core} @ {speed:.2} GHz ──── {red}{temp}{reset} °C",
- )?;
- stdout.write_all(&g.buffer)?;
- stdout.flush()?;
-
- g.push_point(usage()?.max(0.01));
-
- sleep(Duration::from_secs_f32(d));
- }
- println!("\x1B[?7l");
- Ok(())
-}
diff --git a/cpu/src/temps.rs b/cpu/src/temps.rs
new file mode 100644
index 0000000..ea0031f
--- /dev/null
+++ b/cpu/src/temps.rs
@@ -0,0 +1,87 @@
+#![feature(let_chains, iter_array_chunks, array_chunks, portable_simd, iter_chain)]
+use anyhow::{ensure, Result};
+use comat::cwrite;
+use cpu::*;
+use grapher::Grapher;
+use std::array;
+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};
+
+fn main() -> Result<()> {
+ 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 info = CpuInfo::read()?;
+ let core = std::env::args()
+ .nth(1)
+ .and_then(|x| x.parse::<u64>().ok())
+ .map_or(ViewCore::All(info.count), ViewCore::One);
+ CORE.set(core).unwrap();
+ match core {
+ ViewCore::One(x) => ensure!(x < info.count, "not enough cores"),
+ _ => (),
+ }
+ let mut t = Temps::load()?;
+
+ let mut g = Grapher::new()?;
+ g.push_point(t.read()? / 105.0);
+
+ 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(
+ [228, 197, 63].map(|x| x as f32 / 255.0), // yellow
+ [0x5c, 0xc7, 0xdd].map(|x| x as f32 / 255.0), // blue
+ y as f32 / (h - 1) as f32,
+ )
+ .map(|x| (x * 255.0) as u8),
+ )
+ })?;
+
+ write!(g.buffer, "{}{}", White.fg_str(), cursor::Goto(1, 1))?;
+ let name = &*info.name;
+ let speed = speed()?;
+ let temp = t.read()?;
+ let fps = (1f32 / d).round();
+ cwrite!(
+ g.buffer,
+ " {fps}fps ──── {name} {core} @ {speed:.2} GHz ──── {red}{temp}{reset} °C",
+ )?;
+ stdout.write_all(&g.buffer)?;
+ stdout.flush()?;
+
+ g.push_point(temp / 105.);
+
+ sleep(Duration::from_secs_f32(d));
+ }
+ println!("\x1B[?7l");
+ Ok(())
+}