50 short programs in Rust, #2
October 12, 2019
I use XFCE4 as my main window manager, and I like its flexibility/customisability. I recently found out about xfce4-genmon-plugin
, which is a "generic monitor" - it runs any command on a configurable interval and includes the output on the XFCE panel. By having that command return XML, it can even display tooltips and images as well as plain text (see https://goodies.xfce.org/projects/panel-plugins/xfce4-genmon-plugin#usage).
While most desktops include something that displays total CPU/RAM/etc. usage in the panel, I find it useful to also see what program is the heaviest user of each. Here's a Rust program (using rust-psutil) which runs for two seconds, then prints out:
- the program which used most CPU over those two seconds,
- and the program which had the highest memory usage at the end
Since it's plain text on one line, it can then be easily hooked into xfce4-genmon-plugin
and look OK.
use std::collections::HashMap; fn main() { let mut original_times = HashMap::new(); for prog in psutil::process::all().expect("Could not get all processes the first time") { original_times.insert(prog.pid, prog.utime + prog.stime); } std::thread::sleep(std::time::Duration::new(2,0)); let mut busiest_process = (String::new(), 0.0); let mut most_ram = (String::new(), 0); for prog in psutil::process::all().expect("Could not get all processes the second time") { let rss = prog.memory().expect(&format!("Could not get memory for {}", prog.comm)).resident; if rss > most_ram.1 { most_ram = (prog.comm.clone(), rss); } if original_times.contains_key(&prog.pid) { let secs_passed = (prog.utime + prog.stime) - original_times[&prog.pid]; if secs_passed > busiest_process.1 { busiest_process = (prog.comm, secs_passed); } } original_times.insert(prog.pid, prog.utime + prog.stime); } if busiest_process.0 == most_ram.0 { println!("{}: {:.1}%, {} MiB", busiest_process.0, (busiest_process.1/2.0)*100.0, most_ram.1/(1024*1024)); } else { println!("{}: {:.1}% / {}: {} MiB", busiest_process.0, (busiest_process.1/2.0)*100.0, most_ram.0, most_ram.1/(1024*1024)); } }
It would be nice if:
- it also printed out the heaviest user of disk I/O - this information is in
/proc/[pid]/io
, so it's just a matter of enhancingrust-psutil
to retrieve it. psutil::process::all()
(or some variant) always returned a best-effort list of processes, instead of failing if a process exited in the brief period between it seeing the/proc/[pid]/
directory and successfully reading all the files in it.
(Code also at https://github.com/rkday/50-short-programs-in-rust/tree/master/hungriest-program.)