#![feature(import_trait_associated_functions, iter_array_chunks, portable_simd)]
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(())
}