diff options
author | Clement Tsang <34804052+ClementTsang@users.noreply.github.com> | 2022-11-21 05:28:42 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-21 05:28:42 -0500 |
commit | 4f00434210a20109f4b9ca27c1b1856f376499b5 (patch) | |
tree | 0ce69bbc487460c2acdecbc84d42e73b6faaecb9 | |
parent | f887096ceae26c06a690c6400569cf2e74a79dec (diff) |
other: non-normalized process CPU% cleanup and docs (#910)
* refactor: simplify non-normalized code
* update docs
* appease clippy
* add comment
* unnormalized
* fix issues on non-Linux regarding typos/imports
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | docs/content/configuration/command-line-flags.md | 79 | ||||
-rw-r--r-- | docs/content/configuration/config-file/flags.md | 65 | ||||
-rw-r--r-- | sample_configs/default_config.toml | 3 | ||||
-rw-r--r-- | src/app.rs | 2 | ||||
-rw-r--r-- | src/app/data_harvester.rs | 58 | ||||
-rw-r--r-- | src/app/data_harvester/processes/freebsd.rs | 4 | ||||
-rw-r--r-- | src/app/data_harvester/processes/linux.rs | 75 | ||||
-rw-r--r-- | src/app/data_harvester/processes/macos.rs | 4 | ||||
-rw-r--r-- | src/app/data_harvester/processes/macos_freebsd.rs | 16 | ||||
-rw-r--r-- | src/app/data_harvester/processes/windows.rs | 8 | ||||
-rw-r--r-- | src/clap.rs | 10 | ||||
-rw-r--r-- | src/constants.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 6 | ||||
-rw-r--r-- | src/options.rs | 12 |
15 files changed, 190 insertions, 155 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index b5b11afe..d134d3f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#870](https://github.com/ClementTsang/bottom/pull/870): Make disk widget sortable. - [#881](https://github.com/ClementTsang/bottom/pull/881): Add pasting to the search bar. - [#892](https://github.com/ClementTsang/bottom/pull/892): Add custom retention periods for data. +- [#899](https://github.com/ClementTsang/bottom/pull/899): Add non-normalized CPU usage to processes. ## [0.6.8] - 2022-02-01 diff --git a/docs/content/configuration/command-line-flags.md b/docs/content/configuration/command-line-flags.md index febf2068..6780e392 100644 --- a/docs/content/configuration/command-line-flags.md +++ b/docs/content/configuration/command-line-flags.md @@ -6,42 +6,43 @@ The following flags can be provided to bottom in the command line to change the behaviour of the program (run `btm --help` for more information on each flag): -| Flag | Behaviour | -| ------------------------------------- | -------------------------------------------------------------- | -| `--autohide_time` | Temporarily shows the time scale in graphs. | -| `-b, --basic` | Hides graphs and uses a more basic look. | -| `--battery` | Shows the battery widget. | -| `-S, --case_sensitive` | Enables case sensitivity by default. | -| `-c, --celsius` | Sets the temperature type to Celsius. | -| `--color <COLOR SCHEME>` | Use a color scheme, use --help for supported values. | -| `-C, --config <CONFIG PATH>` | Sets the location of the config file. | -| `-u, --current_usage` | Sets process CPU% to be based on current CPU%. | -| `-t, --default_time_value <MS>` | Default time value for graphs in ms. | -| `--default_widget_count <INT>` | Sets the n'th selected widget type as the default. | -| `--default_widget_type <WIDGET TYPE>` | Sets the default widget type, use --help for more info. | -| `--disable_advanced_kill` | Hides advanced options to stop a process on Unix-like systems. | -| `--disable_click` | Disables mouse clicks. | -| `-m, --dot_marker` | Uses a dot marker for graphs. | -| `-f, --fahrenheit` | Sets the temperature type to Fahrenheit. | -| `-g, --group` | Groups processes with the same name by default. | -| `-h, --help` | Prints help information. Use --help for more info. | -| `-a, --hide_avg_cpu` | Hides the average CPU usage. | -| `--hide_table_gap` | Hides the spacing between table headers and entries. | -| `--hide_time` | Hides the time scale. | -| `-k, --kelvin` | Sets the temperature type to Kelvin. | -| `-l, --left_legend` | Puts the CPU chart legend to the left side. | -| `--mem_as_value` | Defaults to showing process memory usage by value. | -| `--network_use_binary_prefix` | Displays the network widget with binary prefixes. | -| `--network_use_bytes` | Displays the network widget using bytes. | -| `--network_use_log` | Displays the network widget with a log scale. | -| `--process_command` | Show processes as their commands by default. | -| `-r, --rate <MS>` | Sets a refresh rate in ms. | -| `-R, --regex` | Enables regex by default. | -| `--show_table_scroll_position` | Shows the scroll position tracker in table widgets. | -| `-d, --time_delta <MS>` | The amount in ms changed upon zooming. | -| `-T, --tree` | Defaults to showing the process widget in tree mode. | -| `--use_old_network_legend` | DEPRECATED - uses the older network legend. | -| `-V, --version` | Prints version information. | -| `-W, --whole_word` | Enables whole-word matching by default. | -| `--enable_gpu_memory` | Enable collecting and displaying GPU memory usage. | -| `--retention` | How much data is stored at once in terms of time. | +| Flag | Behaviour | +| ------------------------------------- | --------------------------------------------------------------- | +| `--autohide_time` | Temporarily shows the time scale in graphs. | +| `-b, --basic` | Hides graphs and uses a more basic look. | +| `--battery` | Shows the battery widget. | +| `-S, --case_sensitive` | Enables case sensitivity by default. | +| `-c, --celsius` | Sets the temperature type to Celsius. | +| `--color <COLOR SCHEME>` | Use a color scheme, use --help for supported values. | +| `-C, --config <CONFIG PATH>` | Sets the location of the config file. | +| `-u, --current_usage` | Sets process CPU% to be based on current CPU%. | +| `-t, --default_time_value <MS>` | Default time value for graphs in ms. | +| `--default_widget_count <INT>` | Sets the n'th selected widget type as the default. | +| `--default_widget_type <WIDGET TYPE>` | Sets the default widget type, use --help for more info. | +| `--disable_advanced_kill` | Hides advanced options to stop a process on Unix-like systems. | +| `--disable_click` | Disables mouse clicks. | +| `-m, --dot_marker` | Uses a dot marker for graphs. | +| `-f, --fahrenheit` | Sets the temperature type to Fahrenheit. | +| `-g, --group` | Groups processes with the same name by default. | +| `-h, --help` | Prints help information. Use --help for more info. | +| `-a, --hide_avg_cpu` | Hides the average CPU usage. | +| `--hide_table_gap` | Hides the spacing between table headers and entries. | +| `--hide_time` | Hides the time scale. | +| `-k, --kelvin` | Sets the temperature type to Kelvin. | +| `-l, --left_legend` | Puts the CPU chart legend to the left side. | +| `--mem_as_value` | Defaults to showing process memory usage by value. | +| `--network_use_binary_prefix` | Displays the network widget with binary prefixes. | +| `--network_use_bytes` | Displays the network widget using bytes. | +| `--network_use_log` | Displays the network widget with a log scale. | +| `--process_command` | Show processes as their commands by default. | +| `-r, --rate <MS>` | Sets a refresh rate in ms. | +| `-R, --regex` | Enables regex by default. | +| `--show_table_scroll_position` | Shows the scroll position tracker in table widgets. | +| `-d, --time_delta <MS>` | The amount in ms changed upon zooming. | +| `-T, --tree` | Defaults to showing the process widget in tree mode. | +| `--use_old_network_legend` | DEPRECATED - uses the older network legend. | +| `-V, --version` | Prints version information. | +| `-W, --whole_word` | Enables whole-word matching by default. | +| `--enable_gpu_memory` | Enable collecting and displaying GPU memory usage. | +| `--retention` | How much data is stored at once in terms of time. | +| `--unnormalized_cpu` | Show process CPU% without normalizing over the number of cores. | diff --git a/docs/content/configuration/config-file/flags.md b/docs/content/configuration/config-file/flags.md index 5aa218ca..606eef63 100644 --- a/docs/content/configuration/config-file/flags.md +++ b/docs/content/configuration/config-file/flags.md @@ -6,35 +6,36 @@ Most of the [command line flags](../../command-line-flags) have config file equivalents to avoid having to type them out each time: -| Field | Type | Functionality | -| ---------------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | -| `hide_avg_cpu` | Boolean | Hides the average CPU usage. | -| `dot_marker` | Boolean | Uses a dot marker for graphs. | -| `left_legend` | Boolean | Puts the CPU chart legend to the left side. | -| `current_usage` | Boolean | Sets process CPU% to be based on current CPU%. | -| `group_processes` | Boolean | Groups processes with the same name by default. | -| `case_sensitive` | Boolean | Enables case sensitivity by default. | -| `whole_word` | Boolean | Enables whole-word matching by default. | -| `regex` | Boolean | Enables regex by default. | -| `basic` | Boolean | Hides graphs and uses a more basic look. | -| `use_old_network_legend` | Boolean | DEPRECATED - uses the older network legend. | -| `battery` | Boolean | Shows the battery widget. | -| `rate` | Unsigned Int (represents milliseconds) | Sets a refresh rate in ms. | -| `default_time_value` | Unsigned Int (represents milliseconds) | Default time value for graphs in ms. | -| `time_delta` | Unsigned Int (represents milliseconds) | The amount in ms changed upon zooming. | -| `hide_time` | Boolean | Hides the time scale. | -| `temperature_type` | String (one of ["k", "f", "c", "kelvin", "fahrenheit", "celsius"]) | Sets the temperature unit type. | -| `default_widget_type` | String (one of ["cpu", "proc", "net", "temp", "mem", "disk"], same as layout options) | Sets the default widget type, use --help for more info. | -| `default_widget_count` | Unsigned Int (represents which `default_widget_type`) | Sets the n'th selected widget type as the default. | -| `disable_click` | Boolean | Disables mouse clicks. | -| `color` | String (one of ["default", "default-light", "gruvbox", "gruvbox-light", "nord", "nord-light"]) | Use a color scheme, use --help for supported values. | -| `mem_as_value` | Boolean | Defaults to showing process memory usage by value. | -| `tree` | Boolean | Defaults to showing the process widget in tree mode. | -| `show_table_scroll_position` | Boolean | Shows the scroll position tracker in table widgets. | -| `process_command` | Boolean | Show processes as their commands by default. | -| `disable_advanced_kill` | Boolean | Hides advanced options to stop a process on Unix-like systems. | -| `network_use_binary_prefix` | Boolean | Displays the network widget with binary prefixes. | -| `network_use_bytes` | Boolean | Displays the network widget using bytes. | -| `network_use_log` | Boolean | Displays the network widget with a log scale. | -| `enable_gpu_memory` | Boolean | Shows the GPU memory widget. | -| `retention` | String (human readable time, such as "10m", "1h", etc.) | How much data is stored at once in terms of time. | +| Field | Type | Functionality | +| ---------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | +| `hide_avg_cpu` | Boolean | Hides the average CPU usage. | +| `dot_marker` | Boolean | Uses a dot marker for graphs. | +| `left_legend` | Boolean | Puts the CPU chart legend to the left side. | +| `current_usage` | Boolean | Sets process CPU% to be based on current CPU%. | +| `group_processes` | Boolean | Groups processes with the same name by default. | +| `case_sensitive` | Boolean | Enables case sensitivity by default. | +| `whole_word` | Boolean | Enables whole-word matching by default. | +| `regex` | Boolean | Enables regex by default. | +| `basic` | Boolean | Hides graphs and uses a more basic look. | +| `use_old_network_legend` | Boolean | DEPRECATED - uses the older network legend. | +| `battery` | Boolean | Shows the battery widget. | +| `rate` | Unsigned Int (represents milliseconds) | Sets a refresh rate in ms. | +| `default_time_value` | Unsigned Int (represents milliseconds) | Default time value for graphs in ms. | +| `time_delta` | Unsigned Int (represents milliseconds) | The amount in ms changed upon zooming. | +| `hide_time` | Boolean | Hides the time scale. | +| `temperature_type` | String (one of ["k", "f", "c", "kelvin", "fahrenheit", "celsius"]) | Sets the temperature unit type. | +| `default_widget_type` | String (one of ["cpu", "proc", "net", "temp", "mem", "disk"], same as layout options) | Sets the default widget type, use --help for more info. | +| `default_widget_count` | Unsigned Int (represents which `default_widget_type`) | Sets the n'th selected widget type as the default. | +| `disable_click` | Boolean | Disables mouse clicks. | +| `color` | String (one of ["default", "default-light", "gruvbox", "gruvbox-light", "nord", "nord-light"]) | Use a color scheme, use --help for supported values. | +| `mem_as_value` | Boolean | Defaults to showing process memory usage by value. | +| `tree` | Boolean | Defaults to showing the process widget in tree mode. | +| `show_table_scroll_position` | Boolean | Shows the scroll position tracker in table widgets. | +| `process_command` | Boolean | Show processes as their commands by default. | +| `disable_advanced_kill` | Boolean | Hides advanced options to stop a process on Unix-like systems. | +| `network_use_binary_prefix` | Boolean | Displays the network widget with binary prefixes. | +| `network_use_bytes` | Boolean | Displays the network widget using bytes. | +| `network_use_log` | Boolean | Displays the network widget with a log scale. | +| `enable_gpu_memory` | Boolean | Shows the GPU memory widget. | +| `retention` | String (human readable time, such as "10m", "1h", etc.) | How much data is stored at once in terms of time. | +| `unnormalized_cpu` | Boolean | Show process CPU% without normalizing over the number of cores. | diff --git a/sample_configs/default_config.toml b/sample_configs/default_config.toml index a2eabb38..bab1833d 100644 --- a/sample_configs/default_config.toml +++ b/sample_configs/default_config.toml @@ -18,7 +18,7 @@ # Whether to set CPU% on a process to be based on the total CPU or just current usage. #current_usage = false # Whether to set CPU% on a process to be based on the total CPU or per-core CPU% (not divided by the number of cpus). -#per_core_percentage = false +#unnormalized_cpu = false # Whether to group processes with the same name together by default. #group_processes = false # Whether to make process searching case sensitive by default. @@ -148,7 +148,6 @@ # type="proc" # default=true - # Filters - you can hide specific temperature sensors, network interfaces, and disks using filters. This is admittedly # a bit hard to use as of now, and there is a planned in-app interface for managing this in the future: #[disk_filter] @@ -57,7 +57,7 @@ pub struct AppConfigFields { pub left_legend: bool, pub show_average_cpu: bool, pub use_current_cpu_total: bool, - pub per_core_percentage: bool, + pub unnormalized_cpu: bool, pub use_basic_mode: bool, pub default_time_value: u64, pub time_interval: u64, diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs index 1d28a020..b4d437a5 100644 --- a/src/app/data_harvester.rs +++ b/src/app/data_harvester.rs @@ -112,7 +112,7 @@ pub struct DataCollector { mem_total_kb: u64, temperature_type: temperature::TemperatureType, use_current_cpu_total: bool, - per_core_percentage: bool, + unnormalized_cpu: bool, last_collection_time: Instant, total_rx: u64, total_tx: u64, @@ -145,7 +145,7 @@ impl DataCollector { mem_total_kb: 0, temperature_type: temperature::TemperatureType::Celsius, use_current_cpu_total: false, - per_core_percentage: false, + unnormalized_cpu: false, last_collection_time: Instant::now(), total_rx: 0, total_tx: 0, @@ -237,8 +237,8 @@ impl DataCollector { self.use_current_cpu_total = use_current_cpu_total; } - pub fn set_per_core_percentage(&mut self, per_core_percentage: bool) { - self.per_core_percentage = per_core_percentage; + pub fn set_unnormalized_cpu(&mut self, unnormalized_cpu: bool) { + self.unnormalized_cpu = unnormalized_cpu; } pub fn set_show_average_cpu(&mut self, show_average_cpu: bool) { @@ -327,39 +327,42 @@ impl DataCollector { } if self.widgets_to_harvest.use_proc { - #[cfg(target_os = "linux")] - { - if let Ok(logical_count) = heim::cpu::logical_count().await { - if let Ok(mut process_list) = processes::get_process_data( + 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 + }; + + processes::get_process_data( &mut self.prev_idle, &mut self.prev_non_idle, &mut self.pid_mapping, self.use_current_cpu_total, - self.per_core_percentage, + normalize_cpu, current_instant .duration_since(self.last_collection_time) .as_secs(), self.mem_total_kb, - logical_count, &mut self.user_table, - ) { - // NB: To avoid duplicate sorts on rerenders/events, we sort the processes by PID here. - // We also want to avoid re-sorting *again* since this process list is sorted! - process_list.sort_unstable_by_key(|p| p.pid); - self.data.list_of_processes = Some(process_list); - } + ) } - } - - #[cfg(not(target_os = "linux"))] - { - if let Ok(mut process_list) = { + #[cfg(not(target_os = "linux"))] + { #[cfg(target_family = "unix")] { processes::get_process_data( &self.sys, self.use_current_cpu_total, - self.per_core_percentage, + self.unnormalized_cpu, self.mem_total_kb, &mut self.user_table, ) @@ -369,14 +372,17 @@ impl DataCollector { processes::get_process_data( &self.sys, self.use_current_cpu_total, - self.per_core_percentage, + self.unnormalized_cpu, self.mem_total_kb, ) } - } { - process_list.sort_unstable_by_key(|p| p.pid); - self.data.list_of_processes = Some(process_list); } + } { + // NB: To avoid duplicate sorts on rerenders/events, we sort the processes by PID here. + // We also want to avoid re-sorting *again* later on if we're sorting by PID, since we already + // did it here! + process_list.sort_unstable_by_key(|p| p.pid); + self.data.list_of_processes = Some(process_list); } } diff --git a/src/app/data_harvester/processes/freebsd.rs b/src/app/data_harvester/processes/freebsd.rs index cbcb5eb1..4c5a9e45 100644 --- a/src/app/data_harvester/processes/freebsd.rs +++ b/src/app/data_harvester/processes/freebsd.rs @@ -25,13 +25,13 @@ struct ProcessRow { } pub fn get_process_data( - sys: &System, use_current_cpu_total: bool, per_core_percentage: bool, mem_total_kb: u64, + sys: &System, use_current_cpu_total: bool, unnormalized_cpu: bool, mem_total_kb: u64, user_table: &mut UserTable, ) -> crate::utils::error::Result<Vec<ProcessHarvest>> { super::macos_freebsd::get_process_data( sys, use_current_cpu_total, - per_core_percentage, + unnormalized_cpu, mem_total_kb, user_table, get_freebsd_process_cpu_usage, diff --git a/src/app/data_harvester/processes/linux.rs b/src/app/data_harvester/processes/linux.rs index d024389d..282e56a3 100644 --- a/src/app/data_harvester/processes/linux.rs +++ b/src/app/data_harvester/processes/linux.rs @@ -48,7 +48,15 @@ fn calculate_idle_values(line: &str) -> Point { (idle, non_idle) } -fn cpu_usage_calculation(prev_idle: &mut f64, prev_non_idle: &mut f64) -> error::Result<Point> { +struct CpuUsage { + /// Difference between the total delta and the idle delta. + cpu_usage: f64, + + /// Overall CPU usage as a fraction. + cpu_fraction: f64, +} + +fn cpu_usage_calculation(prev_idle: &mut f64, prev_non_idle: &mut f64) -> error::Result<CpuUsage> { let (idle, non_idle) = { // From SO answer: https://stackoverflow.com/a/23376195 let mut reader = BufReader::new(File::open("/proc/stat")?); @@ -68,38 +76,37 @@ fn cpu_usage_calculation(prev_idle: &mut f64, prev_non_idle: &mut f64) -> error: *prev_non_idle = non_idle; // TODO: Should these return errors instead? - let result = if total_delta - idle_delta != 0.0 { + let cpu_usage = if total_delta - idle_delta != 0.0 { total_delta - idle_delta } else { 1.0 }; - let cpu_percentage = if total_delta != 0.0 { - result / total_delta + let cpu_fraction = if total_delta != 0.0 { + cpu_usage / total_delta } else { 0.0 }; - Ok((result, cpu_percentage)) + Ok(CpuUsage { + cpu_usage, + cpu_fraction, + }) } -/// Returns the usage and a new set of process times. Note: cpu_fraction should be represented WITHOUT the x100 factor! -#[inline] +/// Returns the usage and a new set of process times. +/// +/// NB: cpu_fraction should be represented WITHOUT the x100 factor! fn get_linux_cpu_usage( - stat: &Stat, cpu_usage: f64, cpu_fraction: f64, prev_proc_times: u64, logical_count: u64, - use_current_cpu_total: bool, per_core_percentage: bool, + stat: &Stat, cpu_usage: f64, cpu_fraction: f64, prev_proc_times: u64, + use_current_cpu_total: bool, ) -> (f64, u64) { // Based heavily on https://stackoverflow.com/a/23376195 and https://stackoverflow.com/a/1424556 let new_proc_times = stat.utime + stat.stime; - let diff = (new_proc_times - prev_proc_times) as f64; // I HATE that it's done like this but there isn't a try_from for u64 -> f64... we can accept a bit of loss in the worst case though + let diff = (new_proc_times - prev_proc_times) as f64; // No try_from for u64 -> f64... oh well. if cpu_usage == 0.0 { (0.0, new_proc_times) - } else if per_core_percentage { - ( - diff / cpu_usage * 100_f64 * cpu_fraction * (logical_count as f64), - new_proc_times, - ) } else if use_current_cpu_total { ((diff / cpu_usage) * 100.0, new_proc_times) } else { @@ -107,11 +114,10 @@ fn get_linux_cpu_usage( } } -#[allow(clippy::too_many_arguments)] fn read_proc( prev_proc: &PrevProcDetails, process: &Process, cpu_usage: f64, cpu_fraction: f64, - use_current_cpu_total: bool, per_core_percentage: bool, time_difference_in_secs: u64, - mem_total_kb: u64, logical_count: u64, user_table: &mut UserTable, + use_current_cpu_total: bool, time_difference_in_secs: u64, mem_total_kb: u64, + user_table: &mut UserTable, ) -> error::Result<(ProcessHarvest, u64)> { let stat = process.stat()?; let (command, name) = { @@ -154,9 +160,7 @@ fn read_proc( cpu_usage, cpu_fraction, prev_proc.cpu_time, - logical_count, use_current_cpu_total, - per_core_percentage, ); let parent_pid = Some(stat.ppid); let mem_usage_bytes = stat.rss_bytes()?; @@ -164,7 +168,6 @@ fn read_proc( let mem_usage_percent = mem_usage_kb as f64 / mem_total_kb as f64 * 100.0; // This can fail if permission is denied! - let (total_read_bytes, total_write_bytes, read_bytes_per_sec, write_bytes_per_sec) = if let Ok(io) = process.io() { let total_read_bytes = io.read_bytes; @@ -218,16 +221,38 @@ fn read_proc( )) } -#[allow(clippy::too_many_arguments)] +/// 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 fn get_process_data( prev_idle: &mut f64, prev_non_idle: &mut f64, pid_mapping: &mut FxHashMap<Pid, PrevProcDetails>, use_current_cpu_total: bool, - per_core_percentage: bool, time_difference_in_secs: u64, mem_total_kb: u64, logical_count: u64, + normalization: CpuUsageStrategy, time_difference_in_secs: u64, mem_total_kb: u64, user_table: &mut UserTable, ) -> crate::utils::error::Result<Vec<ProcessHarvest>> { // TODO: [PROC THREADS] Add threads - if let Ok((cpu_usage, cpu_fraction)) = cpu_usage_calculation(prev_idle, prev_non_idle) { + if let Ok(CpuUsage { + mut cpu_usage, + cpu_fraction, + }) = cpu_usage_calculation(prev_idle, prev_non_idle) + { + if let CpuUsageStrategy::NonNormalized(num_cores) = normalization { + // Note we *divide* here because the later calculation divides `cpu_usage` - in effect, + // multiplying over the number of cores. + cpu_usage /= num_cores; + } + let mut pids_to_clear: FxHashSet<Pid> = pid_mapping.keys().cloned().collect(); let process_vector: Vec<ProcessHarvest> = std::fs::read_dir("/proc")? @@ -245,10 +270,8 @@ pub fn get_process_data( cpu_usage, cpu_fraction, use_current_cpu_total, - per_core_percentage, time_difference_in_secs, mem_total_kb, - logical_count, user_table, ) { prev_proc_details.cpu_time = new_process_times; diff --git a/src/app/data_harvester/processes/macos.rs b/src/app/data_harvester/processes/macos.rs index c3570290..a2b61b69 100644 --- a/src/app/data_harvester/processes/macos.rs +++ b/src/app/data_harvester/processes/macos.rs @@ -7,13 +7,13 @@ use crate::{data_harvester::processes::UserTable, Pid}; mod sysctl_bindings; pub fn get_process_data( - sys: &System, use_current_cpu_total: bool, per_core_percentage: bool, mem_total_kb: u64, + sys: &System, use_current_cpu_total: bool, unnormalized_cpu: bool, mem_total_kb: u64, user_table: &mut UserTable, ) -> crate::utils::error::Result<Vec<ProcessHarvest>> { super::macos_freebsd::get_process_data( sys, use_current_cpu_total, - per_core_percentage, + unnormalized_cpu, mem_total_kb, user_table, get_macos_process_cpu_usage, diff --git a/src/app/data_harvester/processes/macos_freebsd.rs b/src/app/data_harvester/processes/macos_freebsd.rs index 3f2e340d..251bc847 100644 --- a/src/app/data_harvester/processes/macos_freebsd.rs +++ b/src/app/data_harvester/processes/macos_freebsd.rs @@ -9,8 +9,8 @@ use super::ProcessHarvest; use crate::{data_harvester::processes::UserTable, utils::error::Result, Pid}; pub fn get_process_data<F>( - sys: &System, use_current_cpu_total: bool, per_core_percentage: bool, mem_total_kb: u64, - user_table: &mut UserTable, get_process_cpu_usage: F, + sys: &System, use_current_cpu_total: bool, unnormalized_cpu: bool, mem_total_kb: u64, + user_table: &mut UserTable, backup_cpu_proc_usage: F, ) -> Result<Vec<ProcessHarvest>> where F: Fn(&[Pid]) -> io::Result<HashMap<Pid, f64>>, @@ -18,6 +18,8 @@ where let mut process_vector: Vec<ProcessHarvest> = Vec::new(); let process_hashmap = sys.processes(); let cpu_usage = sys.global_cpu_info().cpu_usage() as f64 / 100.0; + let num_processors = sys.cpus().len() as f64; + for process_val in process_hashmap.values() { let name = if process_val.name().is_empty() { let process_cmd = process_val.cmd |