summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2023-03-02 00:03:54 -0500
committerGitHub <noreply@github.com>2023-03-02 00:03:54 -0500
commitf26d598410c63dd5fcf6ed10bdd4b56e75697390 (patch)
tree8d2ab7cc494663c4e4796c777ffbc4d53af3d4a0 /src
parente8ae1a265ad52c0ff28dc9edf8dcfe7bc0ed669d (diff)
refactor: migrate CPU from heim to sysinfo for all platforms (#1035)
* refactor: migrate CPU from heim to sysinfo for all platforms * fix windows and macos imports * simplify a bit of code * cleanup
Diffstat (limited to 'src')
-rw-r--r--src/app/data_harvester.rs81
-rw-r--r--src/app/data_harvester/cpu.rs11
-rw-r--r--src/app/data_harvester/cpu/heim.rs159
-rw-r--r--src/app/data_harvester/cpu/heim/linux.rs19
-rw-r--r--src/app/data_harvester/cpu/heim/unix.rs13
-rw-r--r--src/app/data_harvester/cpu/heim/windows_macos.rs12
-rw-r--r--src/app/data_harvester/cpu/sysinfo.rs8
-rw-r--r--src/app/data_harvester/processes/linux.rs45
8 files changed, 55 insertions, 293 deletions
diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs
index e25f0be4..d3c4d715 100644
--- a/src/app/data_harvester.rs
+++ b/src/app/data_harvester.rs
@@ -10,7 +10,6 @@ use fxhash::FxHashMap;
#[cfg(feature = "battery")]
use starship_battery::{Battery, Manager};
-#[cfg(not(target_os = "linux"))]
use sysinfo::{System, SystemExt};
use super::DataFilters;
@@ -99,10 +98,7 @@ impl Data {
#[derive(Debug)]
pub struct DataCollector {
pub data: Data,
- #[cfg(not(target_os = "linux"))]
sys: System,
- previous_cpu_times: Vec<(cpu::PastCpuWork, cpu::PastCpuTotal)>,
- previous_average_cpu_time: Option<(cpu::PastCpuWork, cpu::PastCpuTotal)>,
#[cfg(target_os = "linux")]
pid_mapping: FxHashMap<crate::Pid, processes::PrevProcDetails>,
#[cfg(target_os = "linux")]
@@ -132,10 +128,7 @@ impl DataCollector {
pub fn new(filters: DataFilters) -> Self {
DataCollector {
data: Data::default(),
- #[cfg(not(target_os = "linux"))]
sys: System::new_with_specifics(sysinfo::RefreshKind::new()),
- previous_cpu_times: vec![],
- previous_average_cpu_time: None,
#[cfg(target_os = "linux")]
pid_mapping: FxHashMap::default(),
#[cfg(target_os = "linux")]
@@ -186,16 +179,16 @@ impl DataCollector {
self.sys.refresh_users_list();
}
- if self.widgets_to_harvest.use_proc || self.widgets_to_harvest.use_cpu {
- self.sys.refresh_cpu();
- }
-
// Refresh disk list once...
if cfg!(target_os = "freebsd") && self.widgets_to_harvest.use_disk {
self.sys.refresh_disks_list();
}
}
+ if self.widgets_to_harvest.use_proc || self.widgets_to_harvest.use_cpu {
+ self.sys.refresh_cpu();
+ }
+
#[cfg(feature = "battery")]
{
if self.widgets_to_harvest.use_battery {
@@ -216,8 +209,6 @@ impl DataCollector {
std::thread::sleep(std::time::Duration::from_millis(250));
self.data.cleanup();
-
- // trace!("Enabled widgets to harvest: {:#?}", self.widgets_to_harvest);
}
#[cfg(target_os = "linux")]
@@ -250,11 +241,12 @@ impl DataCollector {
}
pub async fn update_data(&mut self) {
+ if self.widgets_to_harvest.use_proc || self.widgets_to_harvest.use_cpu {
+ self.sys.refresh_cpu();
+ }
+
#[cfg(not(target_os = "linux"))]
{
- if self.widgets_to_harvest.use_proc || self.widgets_to_harvest.use_cpu {
- self.sys.refresh_cpu();
- }
if self.widgets_to_harvest.use_proc {
self.sys.refresh_processes();
}
@@ -284,38 +276,12 @@ impl DataCollector {
// CPU
if self.widgets_to_harvest.use_cpu {
- #[cfg(not(target_os = "freebsd"))]
- {
- if let Ok(cpu_data) = cpu::get_cpu_data_list(
- self.show_average_cpu,
- &mut self.previous_cpu_times,
- &mut self.previous_average_cpu_time,
- )
- .await
- {
- self.data.cpu = Some(cpu_data);
- }
- }
- #[cfg(target_os = "freebsd")]
- {
- if let Ok(cpu_data) = cpu::get_cpu_data_list(
- &self.sys,
- self.show_average_cpu,
- &mut self.previous_cpu_times,
- &mut self.previous_average_cpu_time,
- )
- .await
- {
- self.data.cpu = Some(cpu_data);
- }
- }
+ self.data.cpu = cpu::get_cpu_data_list(&self.sys, self.show_average_cpu).ok();
#[cfg(target_family = "unix")]
{
// Load Average
- if let Ok(load_avg_data) = cpu::get_load_avg().await {
- self.data.load_avg = Some(load_avg_data);
- }
+ self.data.load_avg = cpu::get_load_avg().ok();
}
}
@@ -334,24 +300,23 @@ impl DataCollector {
if let Ok(mut process_list) = {
#[cfg(target_os = "linux")]
{
- // Must do this here since we otherwise have to make `get_process_data` async.
- use self::processes::CpuUsageStrategy;
-
- let normalize_cpu = if self.unnormalized_cpu {
- heim::cpu::logical_count()
- .await
- .map(|v| CpuUsageStrategy::NonNormalized(v as f64))
- .unwrap_or(CpuUsageStrategy::Normalized)
- } else {
- CpuUsageStrategy::Normalized
+ use self::processes::{PrevProc, ProcHarvestOptions};
+
+ let prev_proc = PrevProc {
+ prev_idle: &mut self.prev_idle,
+ prev_non_idle: &mut self.prev_non_idle,
+ };
+
+ let proc_harvest_options = ProcHarvestOptions {
+ use_current_cpu_total: self.use_current_cpu_total,
+ unnormalized_cpu: self.unnormalized_cpu,
};
processes::get_process_data(
- &mut self.prev_idle,
- &mut self.prev_non_idle,
+ &self.sys,
+ prev_proc,
&mut self.pid_mapping,
- self.use_current_cpu_total,
- normalize_cpu,
+ proc_harvest_options,
current_instant
.duration_since(self.last_collection_time)
.as_secs(),
diff --git a/src/app/data_harvester/cpu.rs b/src/app/data_harvester/cpu.rs
index c4131876..a827b26c 100644
--- a/src/app/data_harvester/cpu.rs
+++ b/src/app/data_harvester/cpu.rs
@@ -4,15 +4,8 @@
//!
//! For load average, macOS and Linux are supported through Heim, FreeBSD by sysinfo.
-cfg_if::cfg_if! {
- if #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] {
- pub mod heim;
- pub use self::heim::*;
- } else if #[cfg(target_os = "freebsd")] {
- pub mod sysinfo;
- pub use self::sysinfo::*;
- }
-}
+pub mod sysinfo;
+pub use self::sysinfo::*;
pub type LoadAvgHarvest = [f32; 3];
diff --git a/src/app/data_harvester/cpu/heim.rs b/src/app/data_harvester/cpu/heim.rs
deleted file mode 100644
index f3aa92aa..00000000
--- a/src/app/data_harvester/cpu/heim.rs
+++ /dev/null
@@ -1,159 +0,0 @@
-//! CPU stats through heim.
-//! Supports macOS, Linux, and Windows.
-
-cfg_if::cfg_if! {
- if #[cfg(target_os = "linux")] {
- pub mod linux;
- pub use linux::*;
- } else if #[cfg(any(target_os = "macos", target_os = "windows"))] {
- pub mod windows_macos;
- pub use windows_macos::*;
- }
-}
-
-cfg_if::cfg_if! {
- if #[cfg(target_family = "unix")] {
- pub mod unix;
- pub use unix::*;
- }
-}
-
-use std::collections::VecDeque;
-
-use futures::StreamExt;
-
-use crate::{
- components::tui_widget::time_chart::Point,
- data_harvester::cpu::{CpuData, CpuDataType, CpuHarvest, PastCpuTotal, PastCpuWork},
-};
-
-pub async fn get_cpu_data_list(
- show_average_cpu: bool, previous_cpu_times: &mut Vec<(PastCpuWork, PastCpuTotal)>,
- previous_average_cpu_time: &mut Option<(PastCpuWork, PastCpuTotal)>,
-) -> crate::error::Result<CpuHarvest> {
- fn calculate_cpu_usage_percentage(
- (previous_working_time, previous_total_time): Point,
- (current_working_time, current_total_time): Point,
- ) -> f64 {
- ((if current_working_time > previous_working_time {
- current_working_time - previous_working_time
- } else {
- 0.0
- }) * 100.0)
- / (if current_total_time > previous_total_time {
- current_total_time - previous_total_time
- } else {
- 1.0
- })
- }
-
- // Get all CPU times...
- let cpu_times = heim::cpu::times().await?;
- futures::pin_mut!(cpu_times);
-
- let mut cpu_deque: VecDeque<CpuData> = if previous_cpu_times.is_empty() {
- // Must initialize ourselves. Use a very quick timeout to calculate an initial.
- futures_timer::Delay::new(std::time::Duration::from_millis(100)).await;
-
- let second_cpu_times = heim::cpu::times().await?;
- futures::pin_mut!(second_cpu_times);
-
- let mut new_cpu_times: Vec<(PastCpuWork, PastCpuTotal)> = Vec::new();
- let mut cpu_deque: VecDeque<CpuData> = VecDeque::new();
- let mut collected_zip = cpu_times.zip(second_cpu_times).enumerate(); // Gotta move it here, can't on while line.
-
- while let Some((itx, (past, present))) = collected_zip.next().await {
- if let (Ok(past), Ok(present)) = (past, present) {
- let present_times = convert_cpu_times(&present);
- new_cpu_times.push(present_times);
- cpu_deque.push_back(CpuData {
- data_type: CpuDataType::Cpu(itx),
- cpu_usage: calculate_cpu_usage_percentage(
- convert_cpu_times(&past),
- present_times,
- ),
- });
- } else {
- new_cpu_times.push((0.0, 0.0));
- cpu_deque.push_back(CpuData {
- data_type: CpuDataType::Cpu(itx),
- cpu_usage: 0.0,
- });
- }
- }
-
- *previous_cpu_times = new_cpu_times;
- cpu_deque
- } else {
- let (new_cpu_times, cpu_deque): (Vec<(PastCpuWork, PastCpuTotal)>, VecDeque<CpuData>) =
- cpu_times
- .collect::<Vec<_>>()
- .await
- .iter()
- .zip(&*previous_cpu_times)
- .enumerate()
- .map(|(itx, (current_cpu, (past_cpu_work, past_cpu_total)))| {
- if let Ok(cpu_time) = current_cpu {
- let present_times = convert_cpu_times(cpu_time);
-
- (
- present_times,
- CpuData {
- data_type: CpuDataType::Cpu(itx),
- cpu_usage: calculate_cpu_usage_percentage(
- (*past_cpu_work, *past_cpu_total),
- present_times,
- ),
- },
- )
- } else {
- (
- (*past_cpu_work, *past_cpu_total),
- CpuData {
- data_type: CpuDataType::Cpu(itx),
- cpu_usage: 0.0,
- },
- )
- }
- })
- .unzip();
-
- *previous_cpu_times = new_cpu_times;
- cpu_deque
- };
-
- // Get average CPU if needed... and slap it at the top
- if show_average_cpu {
- let cpu_time = heim::cpu::time().await?;
-
- let (cpu_usage, new_average_cpu_time) = if let Some((past_cpu_work, past_cpu_total)) =
- previous_average_cpu_time
- {
- let present_times = convert_cpu_times(&cpu_time);
- (
- calculate_cpu_usage_percentage((*past_cpu_work, *past_cpu_total), present_times),
- present_times,
- )
- } else {
- // Again, we need to do a quick timeout...
- futures_timer::Delay::new(std::time::Duration::from_millis(100)).await;
- let second_cpu_time = heim::cpu::time().await?;
-
- let present_times = convert_cpu_times(&second_cpu_time);
- (
- calculate_cpu_usage_percentage(convert_cpu_times(&cpu_time), present_times),
- present_times,
- )
- };
-
- *previous_average_cpu_time = Some(new_average_cpu_time);
- cpu_deque.push_front(CpuData {
- data_type: CpuDataType::Avg,
- cpu_usage,
- })
- }
-
- // Ok(Vec::from(cpu_deque.drain(0..3).collect::<Vec<_>>())) // For artificially limiting the CPU results
-
- Ok(Vec::from(cpu_deque))
-}
diff --git a/src/app/data_harvester/cpu/heim/linux.rs b/src/app/data_harvester/cpu/heim/linux.rs
deleted file mode 100644
index f1b040c4..00000000
--- a/src/app/data_harvester/cpu/heim/linux.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-//! Linux-specific functions regarding CPU usage.
-
-use heim::cpu::os::linux::CpuTimeExt;
-
-use crate::components::tui_widget::time_chart::Point;
-
-pub fn convert_cpu_times(cpu_time: &heim::cpu::CpuTime) -> Point {
- let working_time: f64 = (cpu_time.user()
- + cpu_time.nice()
- + cpu_time.system()
- + cpu_time.irq()
- + cpu_time.soft_irq()
- + cpu_time.steal())
- .get::<heim::units::time::second>();
- (
- working_time,
- working_time + (cpu_time.idle() + cpu_time.io_wait()).get::<heim::units::time::second>(),
- )
-}
diff --git a/src/app/data_harvester/cpu/heim/unix.rs b/src/app/data_harvester/cpu/heim/unix.rs
deleted file mode 100644
index 74340951..00000000
--- a/src/app/data_harvester/cpu/heim/unix.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//! Unix-specific functions regarding CPU usage.
-
-use crate::app::data_harvester::cpu::LoadAvgHarvest;
-
-pub async fn get_load_avg() -> crate::error::Result<LoadAvgHarvest> {
- let (one, five, fifteen) = heim::cpu::os::unix::loadavg().await?;
-
- Ok([
- one.get::<heim::units::ratio::ratio>(),
- five.get::<heim::units::ratio::ratio>(),
- fifteen.get::<heim::units::ratio::ratio>(),
- ])
-}
diff --git a/src/app/data_harvester/cpu/heim/windows_macos.rs b/src/app/data_harvester/cpu/heim/windows_macos.rs
deleted file mode 100644
index 6c110aab..00000000
--- a/src/app/data_harvester/cpu/heim/windows_macos.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//! Windows and macOS-specific functions regarding CPU usage.
-
-use crate::components::tui_widget::time_chart::Point;
-
-pub fn convert_cpu_times(cpu_time: &heim::cpu::CpuTime) -> Point {
- let working_time: f64 =
- (cpu_time.user() + cpu_time.system()).get::<heim::units::time::second>();
- (
- working_time,
- working_time + cpu_time.idle().get::<heim::units::time::second>(),
- )
-}
diff --git a/src/app/data_harvester/cpu/sysinfo.rs b/src/app/data_harvester/cpu/sysinfo.rs
index 54318e1b..d3f000a0 100644
--- a/src/app/data_harvester/cpu/sysinfo.rs
+++ b/src/app/data_harvester/cpu/sysinfo.rs
@@ -5,13 +5,11 @@ use std::collections::VecDeque;
use sysinfo::{CpuExt, LoadAvg, System, SystemExt};
-use super::{CpuData, CpuDataType, CpuHarvest, PastCpuTotal, PastCpuWork};
+use super::{CpuData, CpuDataType, CpuHarvest};
use crate::app::data_harvester::cpu::LoadAvgHarvest;
-pub async fn get_cpu_data_list(
+pub fn get_cpu_data_list(
sys: &sysinfo::System, show_average_cpu: bool,
- _previous_cpu_times: &mut [(PastCpuWork, PastCpuTotal)],
- _previous_average_cpu_time: &mut Option<(PastCpuWork, PastCpuTotal)>,
) -> crate::error::Result<CpuHarvest> {
let mut cpu_deque: VecDeque<_> = sys
.cpus()
@@ -35,7 +33,7 @@ pub async fn get_cpu_data_list(
Ok(Vec::from(cpu_deque))
}
-pub async fn get_load_avg() -> crate::error::Result<LoadAvgHarvest> {
+pub fn get_load_avg() -> crate::error::Result<LoadAvgHarvest> {
let sys = System::new();
let LoadAvg { one, five, fifteen } = sys.load_average();
diff --git a/src/app/data_harvester/processes/linux.rs b/src/app/data_harvester/processes/linux.rs
index 282e56a3..a099adb0 100644
--- a/src/app/data_harvester/processes/linux.rs
+++ b/src/app/data_harvester/processes/linux.rs
@@ -5,7 +5,7 @@ use std::io::{BufRead, BufReader};
use fxhash::{FxHashMap, FxHashSet};
use procfs::process::{Process, Stat};
-use sysinfo::ProcessStatus;
+use sysinfo::{ProcessStatus, System};
use super::{ProcessHarvest, UserTable};
use crate::components::tui_widget::time_chart::Point;
@@ -221,25 +221,31 @@ fn read_proc(
))
}
-/// How to calculate CPU usage.
-pub enum CpuUsageStrategy {
- /// Normalized means the displayed usage percentage is divided over the number of CPU cores.
- ///
- /// For example, if the "overall" usage over the entire system is 105%, and there are 5 cores, then
- /// the displayed percentage is 21%.
- Normalized,
-
- /// Non-normalized means that the overall usage over the entire system is shown, without dividing
- /// over the number of cores.
- NonNormalized(f64),
+pub(crate) struct PrevProc<'a> {
+ pub prev_idle: &'a mut f64,
+ pub prev_non_idle: &'a mut f64,
}
-pub fn get_process_data(
- prev_idle: &mut f64, prev_non_idle: &mut f64,
- pid_mapping: &mut FxHashMap<Pid, PrevProcDetails>, use_current_cpu_total: bool,
- normalization: CpuUsageStrategy, time_difference_in_secs: u64, mem_total_kb: u64,
+pub(crate) struct ProcHarvestOptions {
+ pub use_current_cpu_total: bool,
+ pub unnormalized_cpu: bool,
+}
+
+pub(crate) fn get_process_data(
+ sys: &System, prev_proc: PrevProc<'_>, pid_mapping: &mut FxHashMap<Pid, PrevProcDetails>,
+ proc_harvest_options: ProcHarvestOptions, time_difference_in_secs: u64, mem_total_kb: u64,
user_table: &mut UserTable,
) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
+ let ProcHarvestOptions {
+ use_current_cpu_total,
+ unnormalized_cpu,
+ } = proc_harvest_options;
+
+ let PrevProc {
+ prev_idle,
+ prev_non_idle,
+ } = prev_proc;
+
// TODO: [PROC THREADS] Add threads
if let Ok(CpuUsage {
@@ -247,10 +253,13 @@ pub fn get_process_data(
cpu_fraction,
}) = cpu_usage_calculation(prev_idle, prev_non_idle)
{
- if let CpuUsageStrategy::NonNormalized(num_cores) = normalization {
+ if unnormalized_cpu {
+ use sysinfo::SystemExt;
+ let num_processors = sys.cpus().len() as f64;
+
// Note we *divide* here because the later calculation divides `cpu_usage` - in effect,
// multiplying over the number of cores.
- cpu_usage /= num_cores;
+ cpu_usage /= num_processors;
}
let mut pids_to_clear: FxHashSet<Pid> = pid_mapping.keys().cloned().collect();