monitoring kit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#![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(())
}