monitoring kit
temps
| -rw-r--r-- | cpu/Cargo.toml | 11 | ||||
| -rw-r--r-- | cpu/src/cpu.rs | 94 | ||||
| -rw-r--r-- | cpu/src/lib.rs (renamed from cpu/src/main.rs) | 110 | ||||
| -rw-r--r-- | cpu/src/temps.rs | 87 |
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(()) +} |