vmstat&top: reuse cpu load

This commit is contained in:
Bluemangoo
2025-03-27 12:03:41 +00:00
parent 2f0d29c45a
commit ccb2b43a9c
5 changed files with 98 additions and 91 deletions
Generated
+1
View File
@@ -1598,6 +1598,7 @@ dependencies = [
"pkg-config",
"prettytable-rs",
"sysinfo",
"uu_vmstat",
"uucore",
"windows-sys 0.59.0",
]
+4
View File
@@ -20,12 +20,16 @@ prettytable-rs = { workspace = true }
sysinfo = { workspace = true }
chrono = { workspace = true }
bytesize = { workspace = true }
uu_vmstat = { path = "../vmstat" }
[target.'cfg(target_os="windows")'.dependencies]
windows-sys = { workspace = true, features = [
"Win32_System_RemoteDesktop",
"Win32_System_SystemInformation",
] }
[target.'cfg(target_os="linux")'.build-dependencies]
pkg-config = "0.3.31"
+9 -40
View File
@@ -135,49 +135,18 @@ fn task() -> String {
#[cfg(target_os = "linux")]
fn cpu() -> String {
let file = std::fs::File::open(std::path::Path::new("/proc/stat")).unwrap();
let content = std::io::read_to_string(file).unwrap();
let load = content
.lines()
.next()
.unwrap()
.strip_prefix("cpu")
.unwrap()
.split(' ')
.filter(|s| !s.is_empty())
.collect::<Vec<_>>();
let user = load[0].parse::<f64>().unwrap();
let nice = load[1].parse::<f64>().unwrap();
let system = load[2].parse::<f64>().unwrap();
let idle = load[3].parse::<f64>().unwrap_or_default(); // since 2.5.41
let io_wait = load[4].parse::<f64>().unwrap_or_default(); // since 2.5.41
let hardware_interrupt = load[5].parse::<f64>().unwrap_or_default(); // since 2.6.0
let software_interrupt = load[6].parse::<f64>().unwrap_or_default(); // since 2.6.0
let steal_time = load[7].parse::<f64>().unwrap_or_default(); // since 2.6.11
// GNU do not show guest and guest_nice
let guest = load[8].parse::<f64>().unwrap_or_default(); // since 2.6.24
let guest_nice = load[9].parse::<f64>().unwrap_or_default(); // since 2.6.33
let total = user
+ nice
+ system
+ idle
+ io_wait
+ hardware_interrupt
+ software_interrupt
+ steal_time
+ guest
+ guest_nice;
let cpu_load = uu_vmstat::CpuLoad::current();
format!(
"%Cpu(s): {:.1} us, {:.1} sy, {:.1} ni, {:.1} id, {:.1} wa, {:.1} hi, {:.1} si, {:.1} st",
user / total * 100.0,
system / total * 100.0,
nice / total * 100.0,
idle / total * 100.0,
io_wait / total * 100.0,
hardware_interrupt / total * 100.0,
software_interrupt / total * 100.0,
steal_time / total * 100.0,
cpu_load.user,
cpu_load.system,
cpu_load.nice,
cpu_load.idle,
cpu_load.io_wait,
cpu_load.hardware_interrupt,
cpu_load.software_interrupt,
cpu_load.steal_time,
)
}
+78
View File
@@ -0,0 +1,78 @@
#[cfg(target_os = "linux")]
pub fn parse_proc_file(path: &str) -> std::collections::HashMap<String, String> {
let file = std::fs::File::open(std::path::Path::new(path)).unwrap();
let content = std::io::read_to_string(file).unwrap();
let mut map: std::collections::HashMap<String, String> = std::collections::HashMap::new();
for line in content.lines() {
let parts = line.split_once(char::is_whitespace);
if let Some(parts) = parts {
map.insert(parts.0.to_string(), parts.1.trim_start().to_string());
}
}
map
}
#[cfg(target_os = "linux")]
pub struct CpuLoad {
pub user: f64,
pub nice: f64,
pub system: f64,
pub idle: f64,
pub io_wait: f64,
pub hardware_interrupt: f64,
pub software_interrupt: f64,
pub steal_time: f64,
pub guest: f64,
pub guest_nice: f64,
}
#[cfg(target_os = "linux")]
impl CpuLoad {
pub fn current() -> CpuLoad {
let file = std::fs::File::open(std::path::Path::new("/proc/stat")).unwrap(); // do not use `parse_proc_file` here because only one line is used
let content = std::io::read_to_string(file).unwrap();
let load = content
.lines()
.next()
.unwrap()
.strip_prefix("cpu")
.unwrap()
.split(' ')
.filter(|s| !s.is_empty())
.collect::<Vec<_>>();
let user = load[0].parse::<f64>().unwrap();
let nice = load[1].parse::<f64>().unwrap();
let system = load[2].parse::<f64>().unwrap();
let idle = load[3].parse::<f64>().unwrap_or_default(); // since 2.5.41
let io_wait = load[4].parse::<f64>().unwrap_or_default(); // since 2.5.41
let hardware_interrupt = load[5].parse::<f64>().unwrap_or_default(); // since 2.6.0
let software_interrupt = load[6].parse::<f64>().unwrap_or_default(); // since 2.6.0
let steal_time = load[7].parse::<f64>().unwrap_or_default(); // since 2.6.11
let guest = load[8].parse::<f64>().unwrap_or_default(); // since 2.6.24
let guest_nice = load[9].parse::<f64>().unwrap_or_default(); // since 2.6.33
let total = user
+ nice
+ system
+ idle
+ io_wait
+ hardware_interrupt
+ software_interrupt
+ steal_time
+ guest
+ guest_nice;
Self {
user: user / total * 100.0,
system: system / total * 100.0,
nice: nice / total * 100.0,
idle: idle / total * 100.0,
io_wait: io_wait / total * 100.0,
hardware_interrupt: hardware_interrupt / total * 100.0,
software_interrupt: software_interrupt / total * 100.0,
steal_time: steal_time / total * 100.0,
guest: guest / total * 100.0,
guest_nice: guest_nice / total * 100.0,
}
}
}
+6 -51
View File
@@ -3,11 +3,13 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
mod parser;
use clap::{crate_version, Command};
#[allow(unused_imports)]
pub use parser::*;
#[cfg(target_os = "linux")]
use procfs::{Current, CurrentSI};
#[cfg(target_os = "linux")]
use std::collections::HashMap;
use uucore::error::UResult;
use uucore::{format_usage, help_about, help_usage};
@@ -75,22 +77,6 @@ fn up_secs_proc() -> f64 {
n_proc as f64 * up_secs()
}
#[cfg(target_os = "linux")]
fn parse_proc_file(path: &str) -> HashMap<String, String> {
let file = std::fs::File::open(std::path::Path::new(path)).unwrap();
let content = std::io::read_to_string(file).unwrap();
let mut map: HashMap<String, String> = HashMap::new();
for line in content.lines() {
let parts = line.split_once(char::is_whitespace);
if let Some(parts) = parts {
map.insert(parts.0.to_string(), parts.1.trim_start().to_string());
}
}
map
}
#[cfg(target_os = "linux")]
fn get_process_info() -> (String, String, String) {
let stat = procfs::KernelStats::current().unwrap();
@@ -180,45 +166,14 @@ fn get_system_info() -> (String, String, String) {
#[cfg(target_os = "linux")]
fn get_cpu_info() -> (String, String, String) {
let stat = parse_proc_file("/proc/stat");
let load = stat
.get("cpu")
.unwrap()
.split(' ')
.filter(|s| !s.is_empty())
.collect::<Vec<_>>();
let user = load[0].parse::<f64>().unwrap();
let nice = load[1].parse::<f64>().unwrap();
let system = load[2].parse::<f64>().unwrap();
let idle = load[3].parse::<f64>().unwrap_or_default(); // since 2.5.41
let io_wait = load[4].parse::<f64>().unwrap_or_default(); // since 2.5.41
let hardware_interrupt = load[5].parse::<f64>().unwrap_or_default(); // since 2.6.0
let software_interrupt = load[6].parse::<f64>().unwrap_or_default(); // since 2.6.0
let steal_time = load[7].parse::<f64>().unwrap_or_default(); // since 2.6.11
// GNU do not show guest and guest_nice
let guest = load[8].parse::<f64>().unwrap_or_default(); // since 2.6.24
let guest_nice = load[9].parse::<f64>().unwrap_or_default(); // since 2.6.33
let total = user
+ nice
+ system
+ idle
+ io_wait
+ hardware_interrupt
+ software_interrupt
+ steal_time
+ guest
+ guest_nice;
let cpu_load = CpuLoad::current();
(
"------cpu-----".into(),
"us sy id wa st".into(),
format!(
"{:>2.0} {:>2.0} {:>2.0} {:>2.0} {:>2.0}",
user / total * 100.0,
system / total * 100.0,
idle / total * 100.0,
io_wait / total * 100.0,
steal_time / total * 100.0,
cpu_load.user, cpu_load.system, cpu_load.idle, cpu_load.io_wait, cpu_load.steal_time
),
)
}