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
#![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(())
}