diff options
author | ClementTsang <clementjhtsang@gmail.com> | 2019-12-31 22:24:54 -0500 |
---|---|---|
committer | ClementTsang <clementjhtsang@gmail.com> | 2019-12-31 22:24:54 -0500 |
commit | e5749234a2a96427a04d647a14c92c3bb1e89809 (patch) | |
tree | 808dcbb94feb42cc1b592bdc6286bee9704b7e25 | |
parent | d0a7a0dd72b6b23995a725fd460f2d97b6eff11e (diff) |
Add new option to allow for seeing cpu usage in processes as a percentage of current usage, rather than total
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | src/app.rs | 3 | ||||
-rw-r--r-- | src/app/data_collection.rs | 14 | ||||
-rw-r--r-- | src/app/data_collection/processes.rs | 21 | ||||
-rw-r--r-- | src/main.rs | 4 |
5 files changed, 36 insertions, 8 deletions
@@ -46,6 +46,8 @@ Note that all options and keybindings on GitHub may reflect the current developm - `-l`, `--left_legend` will move external table legends to the left side rather than the right side. Right side is default. +- `-u`, `--current_usage` will make a process' CPU usage be based on the current total CPU usage, rather than assuming 100% CPU usage. Only affects Linux. + ### Keybindings #### General @@ -47,12 +47,14 @@ pub struct App { pub show_help: bool, pub is_frozen: bool, pub left_legend: bool, + pub use_current_cpu_total: bool, last_key_press: Instant, } impl App { pub fn new( show_average_cpu: bool, temperature_type: temperature::TemperatureType, update_rate_in_milliseconds: u64, use_dot: bool, left_legend: bool, + use_current_cpu_total: bool, ) -> App { App { process_sorting_type: processes::ProcessSorting::CPU, @@ -76,6 +78,7 @@ impl App { show_help: false, is_frozen: false, left_legend, + use_current_cpu_total, last_key_press: Instant::now(), } } diff --git a/src/app/data_collection.rs b/src/app/data_collection.rs index 325c83e7..64a1f024 100644 --- a/src/app/data_collection.rs +++ b/src/app/data_collection.rs @@ -49,6 +49,7 @@ pub struct DataState { prev_net_access_time: Instant, temperature_type: temperature::TemperatureType, last_clean: Instant, // Last time stale data was cleared + use_current_cpu_total: bool, } impl Default for DataState { @@ -66,6 +67,7 @@ impl Default for DataState { prev_net_access_time: Instant::now(), temperature_type: temperature::TemperatureType::Celsius, last_clean: Instant::now(), + use_current_cpu_total: false, } } } @@ -75,6 +77,10 @@ impl DataState { self.temperature_type = temperature_type; } + pub fn set_use_current_cpu_total(&mut self, use_current_cpu_total: bool) { + self.use_current_cpu_total = use_current_cpu_total; + } + pub fn init(&mut self) { self.sys.refresh_all(); } @@ -104,7 +110,13 @@ impl DataState { push_if_valid(&mem::get_mem_data_list().await, &mut self.data.memory); push_if_valid(&mem::get_swap_data_list().await, &mut self.data.swap); set_if_valid( - &processes::get_sorted_processes_list(&self.sys, &mut self.prev_idle, &mut self.prev_non_idle, &mut self.prev_pid_stats), + &processes::get_sorted_processes_list( + &self.sys, + &mut self.prev_idle, + &mut self.prev_non_idle, + &mut self.prev_pid_stats, + self.use_current_cpu_total, + ), &mut self.data.list_of_processes, ); diff --git a/src/app/data_collection/processes.rs b/src/app/data_collection/processes.rs index 0eda01f5..16e612c1 100644 --- a/src/app/data_collection/processes.rs +++ b/src/app/data_collection/processes.rs @@ -82,7 +82,7 @@ fn cpu_usage_calculation(prev_idle: &mut f64, prev_non_idle: &mut f64) -> error: let cpu_percentage = if total_delta != 0_f64 { result / total_delta } else { 0_f64 }; - Ok((result, cpu_percentage)) // This works, REALLY damn well. The percentage check is within like 2% of the sysinfo one. + Ok((result, cpu_percentage)) } fn get_ordering<T: std::cmp::PartialOrd>(a_val: T, b_val: T, reverse_order: bool) -> std::cmp::Ordering { @@ -104,7 +104,7 @@ fn get_ordering<T: std::cmp::PartialOrd>(a_val: T, b_val: T, reverse_order: bool } Ordering::Equal => Ordering::Equal, }, - None => Ordering::Equal, // I don't really like this but I think it's fine... + None => Ordering::Equal, } } @@ -125,7 +125,9 @@ fn get_process_cpu_stats(pid: u32) -> std::io::Result<f64> { } /// Note that cpu_percentage should be represented WITHOUT the \times 100 factor! -fn linux_cpu_usage(pid: u32, cpu_usage: f64, cpu_percentage: f64, previous_pid_stats: &mut HashMap<String, (f64, Instant)>) -> std::io::Result<f64> { +fn linux_cpu_usage( + pid: u32, cpu_usage: f64, cpu_percentage: f64, previous_pid_stats: &mut HashMap<String, (f64, Instant)>, use_current_cpu_total: bool, +) -> std::io::Result<f64> { // Based heavily on https://stackoverflow.com/a/23376195 and https://stackoverflow.com/a/1424556 let before_proc_val: f64 = if previous_pid_stats.contains_key(&pid.to_string()) { previous_pid_stats.get(&pid.to_string()).unwrap_or(&(0_f64, Instant::now())).0 @@ -145,11 +147,15 @@ fn linux_cpu_usage(pid: u32, cpu_usage: f64, cpu_percentage: f64, previous_pid_s let entry = previous_pid_stats.entry(pid.to_string()).or_insert((after_proc_val, Instant::now())); *entry = (after_proc_val, Instant::now()); - Ok((after_proc_val - before_proc_val) / cpu_usage * 100_f64 * cpu_percentage) + if use_current_cpu_total { + Ok((after_proc_val - before_proc_val) / cpu_usage * 100_f64) + } else { + Ok((after_proc_val - before_proc_val) / cpu_usage * 100_f64 * cpu_percentage) + } } fn convert_ps( - process: &str, cpu_usage: f64, cpu_percentage: f64, prev_pid_stats: &mut HashMap<String, (f64, Instant)>, + process: &str, cpu_usage: f64, cpu_percentage: f64, prev_pid_stats: &mut HashMap<String, (f64, Instant)>, use_current_cpu_total: bool, ) -> std::io::Result<ProcessData> { if process.trim().to_string().is_empty() { return Ok(ProcessData { @@ -170,12 +176,13 @@ fn convert_ps( command, mem_usage_percent, mem_usage_kb: None, - cpu_usage_percent: linux_cpu_usage(pid, cpu_usage, cpu_percentage, prev_pid_stats)?, + cpu_usage_percent: linux_cpu_usage(pid, cpu_usage, cpu_percentage, prev_pid_stats, use_current_cpu_total)?, }) } pub fn get_sorted_processes_list( sys: &System, prev_idle: &mut f64, prev_non_idle: &mut f64, prev_pid_stats: &mut std::collections::HashMap<String, (f64, Instant)>, + use_current_cpu_total: bool, ) -> crate::utils::error::Result<Vec<ProcessData>> { let mut process_vector: Vec<ProcessData> = Vec::new(); @@ -191,7 +198,7 @@ pub fn get_sorted_processes_list( let process_stream = split_string.collect::<Vec<&str>>(); for process in process_stream { - if let Ok(process_object) = convert_ps(process, cpu_usage, cpu_percentage, prev_pid_stats) { + if let Ok(process_object) = convert_ps(process, cpu_usage, cpu_percentage, prev_pid_stats, use_current_cpu_total) { if !process_object.command.is_empty() { process_vector.push(process_object); } diff --git a/src/main.rs b/src/main.rs index 1f2e9f84..dc54281e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -66,6 +66,7 @@ fn main() -> error::Result<()> { ) (@arg RATE_MILLIS: -r --rate +takes_value "Sets a refresh rate in milliseconds; the minimum is 250ms, defaults to 1000ms. Smaller values may take more resources.") (@arg LEFT_LEGEND: -l --left_legend "Puts external chart legends on the left side rather than the default right side.") + (@arg USE_CURR_USAGE: -u --current_usage "Within Linux, sets a process' CPU usage to be based on the total current CPU usage, rather than assuming 100% usage.") //(@arg CONFIG_LOCATION: -co --config +takes_value "Sets the location of the config file. Expects a config file in the JSON format.") //(@arg BASIC_MODE: -b --basic "Sets bottom to basic mode, not showing graphs and only showing basic tables.") ) @@ -107,6 +108,7 @@ fn main() -> error::Result<()> { let show_average_cpu = matches.is_present("AVG_CPU"); let use_dot = matches.is_present("DOT_MARKER"); let left_legend = matches.is_present("LEFT_LEGEND"); + let use_current_cpu_total = matches.is_present("USE_CURR_USAGE"); // Create "app" struct, which will control most of the program and store settings/state let mut app = app::App::new( @@ -115,6 +117,7 @@ fn main() -> error::Result<()> { update_rate_in_milliseconds as u64, use_dot, left_legend, + use_current_cpu_total, ); // Set up up tui and crossterm @@ -169,6 +172,7 @@ fn main() -> error::Result<()> { let mut data_state = data_collection::DataState::default(); data_state.init(); data_state.set_temperature_type(temp_type); + data_state.set_use_current_cpu_total(use_current_cpu_total); loop { if let Ok(message) = rrx.try_recv() { match message { |