feature: Add appox. total mem as an option for processes and basic mem

Adds a way to display the memory value as a column in the processes widget and the basic memory widget, rather than just the percentage.
This commit is contained in:
Clement Tsang 2020-08-17 12:41:37 -07:00 committed by GitHub
parent 59ce90f577
commit 3c373d7129
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 226 additions and 70 deletions

View File

@ -20,6 +20,7 @@
"haase", "haase",
"heim", "heim",
"hjkl", "hjkl",
"libc",
"markdownlint", "markdownlint",
"minwindef", "minwindef",
"noheader", "noheader",
@ -32,6 +33,7 @@
"softirq", "softirq",
"stime", "stime",
"subwidget", "subwidget",
"sysconf",
"sysinfo", "sysinfo",
"tokei", "tokei",
"twrite", "twrite",
@ -39,6 +41,7 @@
"use", "use",
"use curr usage", "use curr usage",
"utime", "utime",
"virt",
"whitespaces", "whitespaces",
"winapi", "winapi",
"winnt", "winnt",

View File

@ -41,8 +41,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Features ### Features
- [#114](https://github.com/ClementTsang/bottom/pull/114): Show process state per process (originally in 0.4.0, moved to later). This only - [#114](https://github.com/ClementTsang/bottom/pull/114): Show process state per process (originally in 0.4.0, moved to later). This only shows if the processes are not merged together; I couldn't think of a nice way to show it when grouped together, unfortunately.
shows if the processes are not merged together; I couldn't think of a nice way to show it when grouped together, unfortunately.
- Add (estimated) memory usage values, toggle this from percent to values for processes with `%`.
### Changes ### Changes

4
Cargo.lock generated
View File

@ -762,9 +762,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.70" version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f" checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
[[package]] [[package]]
name = "lock_api" name = "lock_api"

View File

@ -38,6 +38,7 @@ backtrace = "0.3"
serde = {version = "1.0", features = ["derive"] } serde = {version = "1.0", features = ["derive"] }
unicode-segmentation = "1.6.0" unicode-segmentation = "1.6.0"
unicode-width = "0.1.7" unicode-width = "0.1.7"
# libc = "0.2.74"
# tui = {version = "0.10.0", features = ["crossterm"], default-features = false, git = "https://github.com/fdehau/tui-rs.git"} # tui = {version = "0.10.0", features = ["crossterm"], default-features = false, git = "https://github.com/fdehau/tui-rs.git"}
tui = {version = "0.9.5", features = ["crossterm"], default-features = false } tui = {version = "0.9.5", features = ["crossterm"], default-features = false }

View File

@ -225,6 +225,7 @@ Run using `btm`.
| `P` | Toggle between showing the full path or just the process name | | `P` | Toggle between showing the full path or just the process name |
| `s, F6` | Open process sort widget | | `s, F6` | Open process sort widget |
| `I` | Invert current sort | | `I` | Invert current sort |
| `%` | Toggle between values and percentages for memory usage |
#### Process search bindings #### Process search bindings
@ -260,6 +261,12 @@ Run using `btm`.
| `Left, Alt-h` | Go to the next battery | | `Left, Alt-h` | Go to the next battery |
| `Right, Alt-l` | Go to the previous battery | | `Right, Alt-l` | Go to the previous battery |
#### Basic memory bindings
| | |
| --- | ------------------------------------------------------ |
| `%` | Toggle between values and percentages for memory usage |
### Process searching keywords ### Process searching keywords
- Note none of the keywords are case sensitive. - Note none of the keywords are case sensitive.

View File

@ -80,6 +80,9 @@ pub struct App {
#[builder(default = false, setter(skip))] #[builder(default = false, setter(skip))]
pub is_force_redraw: bool, pub is_force_redraw: bool,
#[builder(default = false, setter(skip))]
pub basic_mode_use_percent: bool,
pub cpu_state: CpuState, pub cpu_state: CpuState,
pub mem_state: MemState, pub mem_state: MemState,
pub net_state: NetState, pub net_state: NetState,
@ -342,6 +345,30 @@ impl App {
} }
} }
pub fn toggle_percentages(&mut self) {
match &self.current_widget.widget_type {
BottomWidgetType::BasicMem => {
self.basic_mode_use_percent = !self.basic_mode_use_percent; // Oh god this is so lazy.
}
BottomWidgetType::Proc => {
if let Some(proc_widget_state) = self
.proc_state
.widget_states
.get_mut(&self.current_widget.widget_id)
{
proc_widget_state
.columns
.toggle(&processes::ProcessSorting::Mem);
proc_widget_state
.columns
.toggle(&processes::ProcessSorting::MemPercent);
self.proc_state.force_update = Some(self.current_widget.widget_id);
}
}
_ => {}
}
}
pub fn toggle_ignore_case(&mut self) { pub fn toggle_ignore_case(&mut self) {
let is_in_search_widget = self.is_in_search_widget(); let is_in_search_widget = self.is_in_search_widget();
if let Some(proc_widget_state) = self if let Some(proc_widget_state) = self
@ -1111,6 +1138,7 @@ impl App {
'e' => self.expand_widget(), 'e' => self.expand_widget(),
's' => self.toggle_sort(), 's' => self.toggle_sort(),
'I' => self.invert_sort(), 'I' => self.invert_sort(),
'%' => self.toggle_percentages(),
_ => {} _ => {}
} }

View File

@ -87,6 +87,7 @@ pub struct DataCollector {
widgets_to_harvest: UsedWidgets, widgets_to_harvest: UsedWidgets,
battery_manager: Option<Manager>, battery_manager: Option<Manager>,
battery_list: Option<Vec<Battery>>, battery_list: Option<Vec<Battery>>,
// page_file_size_kb: u64,
} }
impl Default for DataCollector { impl Default for DataCollector {
@ -110,6 +111,11 @@ impl Default for DataCollector {
widgets_to_harvest: UsedWidgets::default(), widgets_to_harvest: UsedWidgets::default(),
battery_manager: None, battery_manager: None,
battery_list: None, battery_list: None,
// page_file_size_kb: if cfg!(target_os = "linux") {
// unsafe { libc::sysconf(libc::_SC_PAGESIZE) as u64 / 1024 }
// } else {
// 0
// },
} }
} }
} }
@ -200,6 +206,7 @@ impl DataCollector {
current_instant current_instant
.duration_since(self.last_collection_time) .duration_since(self.last_collection_time)
.as_secs(), .as_secs(),
self.mem_total_kb,
) )
} }
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]

View File

@ -53,8 +53,8 @@ pub async fn get_network_data(
(0, 0) (0, 0)
} else { } else {
( (
((total_rx - *prev_net_rx) as f64 / elapsed_time) as u64, ((total_rx.saturating_sub(*prev_net_rx)) as f64 / elapsed_time) as u64,
((total_tx - *prev_net_tx) as f64 / elapsed_time) as u64, ((total_tx.saturating_sub(*prev_net_tx)) as f64 / elapsed_time) as u64,
) )
}; };

View File

@ -62,6 +62,9 @@ pub struct ProcessHarvest {
pub pid: u32, pub pid: u32,
pub cpu_usage_percent: f64, pub cpu_usage_percent: f64,
pub mem_usage_percent: f64, pub mem_usage_percent: f64,
pub mem_usage_kb: u64,
// pub rss_kb: u64,
// pub virt_kb: u64,
pub name: String, pub name: String,
pub path: String, pub path: String,
pub read_bytes_per_sec: u64, pub read_bytes_per_sec: u64,
@ -224,12 +227,13 @@ fn get_linux_cpu_usage(
} }
} }
#[allow(clippy::too_many_arguments)]
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn convert_ps<S: core::hash::BuildHasher>( fn convert_ps<S: core::hash::BuildHasher>(
process: &str, cpu_usage: f64, cpu_fraction: f64, process: &str, cpu_usage: f64, cpu_fraction: f64,
prev_pid_stats: &mut HashMap<u32, PrevProcDetails, S>, prev_pid_stats: &mut HashMap<u32, PrevProcDetails, S>,
new_pid_stats: &mut HashMap<u32, PrevProcDetails, S>, use_current_cpu_total: bool, new_pid_stats: &mut HashMap<u32, PrevProcDetails, S>, use_current_cpu_total: bool,
time_difference_in_secs: u64, time_difference_in_secs: u64, mem_total_kb: u64,
) -> std::io::Result<ProcessHarvest> { ) -> std::io::Result<ProcessHarvest> {
let pid = (&process[..10]) let pid = (&process[..10])
.trim() .trim()
@ -313,6 +317,7 @@ fn convert_ps<S: core::hash::BuildHasher>(
name, name,
path, path,
mem_usage_percent, mem_usage_percent,
mem_usage_kb: (mem_usage_percent * mem_total_kb as f64 / 100.0) as u64,
cpu_usage_percent, cpu_usage_percent,
total_read_bytes, total_read_bytes,
total_write_bytes, total_write_bytes,
@ -327,7 +332,7 @@ fn convert_ps<S: core::hash::BuildHasher>(
pub fn linux_get_processes_list( pub fn linux_get_processes_list(
prev_idle: &mut f64, prev_non_idle: &mut f64, prev_idle: &mut f64, prev_non_idle: &mut f64,
prev_pid_stats: &mut HashMap<u32, PrevProcDetails, RandomState>, use_current_cpu_total: bool, prev_pid_stats: &mut HashMap<u32, PrevProcDetails, RandomState>, use_current_cpu_total: bool,
time_difference_in_secs: u64, time_difference_in_secs: u64, mem_total_kb: u64,
) -> crate::utils::error::Result<Vec<ProcessHarvest>> { ) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
let ps_result = Command::new("ps") let ps_result = Command::new("ps")
.args(&["-axo", "pid:10,comm:100,%mem:5,args:100", "--noheader"]) .args(&["-axo", "pid:10,comm:100,%mem:5,args:100", "--noheader"])
@ -336,7 +341,6 @@ pub fn linux_get_processes_list(
let split_string = ps_stdout.split('\n'); let split_string = ps_stdout.split('\n');
if let Ok((cpu_usage, cpu_fraction)) = cpu_usage_calculation(prev_idle, prev_non_idle) { if let Ok((cpu_usage, cpu_fraction)) = cpu_usage_calculation(prev_idle, prev_non_idle) {
let process_list = split_string.collect::<Vec<&str>>(); let process_list = split_string.collect::<Vec<&str>>();
let mut new_pid_stats = HashMap::new(); let mut new_pid_stats = HashMap::new();
let process_vector: Vec<ProcessHarvest> = process_list let process_vector: Vec<ProcessHarvest> = process_list
@ -352,6 +356,7 @@ pub fn linux_get_processes_list(
&mut new_pid_stats, &mut new_pid_stats,
use_current_cpu_total, use_current_cpu_total,
time_difference_in_secs, time_difference_in_secs,
mem_total_kb,
) { ) {
if !process_object.name.is_empty() { if !process_object.name.is_empty() {
Some(process_object) Some(process_object)
@ -431,6 +436,7 @@ pub fn windows_macos_get_processes_list(
} else { } else {
0.0 0.0
}, },
mem_usage_kb: process_val.memory(),
cpu_usage_percent: process_cpu_usage, cpu_usage_percent: process_cpu_usage,
read_bytes_per_sec: disk_usage.read_bytes, read_bytes_per_sec: disk_usage.read_bytes,
write_bytes_per_sec: disk_usage.written_bytes, write_bytes_per_sec: disk_usage.written_bytes,

View File

@ -671,12 +671,12 @@ impl Prefix {
match prefix_type { match prefix_type {
PrefixType::Cpu => matches_condition( PrefixType::Cpu => matches_condition(
&numerical_query.condition, &numerical_query.condition,
process.cpu_usage, process.cpu_percent_usage,
numerical_query.value, numerical_query.value,
), ),
PrefixType::Mem => matches_condition( PrefixType::Mem => matches_condition(
&numerical_query.condition, &numerical_query.condition,
process.mem_usage, process.mem_percent_usage,
numerical_query.value, numerical_query.value,
), ),
PrefixType::Rps => matches_condition( PrefixType::Rps => matches_condition(

View File

@ -165,6 +165,7 @@ impl Default for ProcColumn {
ProcessName, ProcessName,
Command, Command,
CpuPercent, CpuPercent,
Mem,
MemPercent, MemPercent,
ReadPerSecond, ReadPerSecond,
WritePerSecond, WritePerSecond,
@ -187,7 +188,7 @@ impl Default for ProcColumn {
}, },
); );
} }
MemPercent | Mem => { MemPercent => {
column_mapping.insert( column_mapping.insert(
column, column,
ColumnInfo { ColumnInfo {
@ -196,6 +197,15 @@ impl Default for ProcColumn {
}, },
); );
} }
Mem => {
column_mapping.insert(
column,
ColumnInfo {
enabled: false,
shortcut: Some("m"),
},
);
}
ProcessName => { ProcessName => {
column_mapping.insert( column_mapping.insert(
column, column,
@ -250,6 +260,20 @@ impl Default for ProcColumn {
} }
impl ProcColumn { impl ProcColumn {
pub fn toggle(&mut self, column: &ProcessSorting) {
if let Some(mapping) = self.column_mapping.get_mut(column) {
mapping.enabled = !(mapping.enabled);
}
}
pub fn is_enabled(&self, column: &ProcessSorting) -> bool {
if let Some(mapping) = self.column_mapping.get(column) {
mapping.enabled
} else {
false
}
}
pub fn get_enabled_columns_len(&self) -> usize { pub fn get_enabled_columns_len(&self) -> usize {
self.ordered_columns self.ordered_columns
.iter() .iter()

View File

@ -42,8 +42,10 @@ pub struct DisplayableData {
pub process_data: Vec<ConvertedProcessData>, pub process_data: Vec<ConvertedProcessData>,
// What's actually displayed // What's actually displayed
pub finalized_process_data_map: HashMap<u64, Vec<ConvertedProcessData>>, pub finalized_process_data_map: HashMap<u64, Vec<ConvertedProcessData>>,
pub mem_label: String, pub mem_label_percent: String,
pub swap_label: String, pub swap_label_percent: String,
pub mem_label_frac: String,
pub swap_label_frac: String,
pub mem_data: Vec<(f64, f64)>, pub mem_data: Vec<(f64, f64)>,
pub swap_data: Vec<(f64, f64)>, pub swap_data: Vec<(f64, f64)>,
pub cpu_data: Vec<ConvertedCpuData>, pub cpu_data: Vec<ConvertedCpuData>,

View File

@ -76,7 +76,7 @@ impl HelpDialog for Painter {
app_state.help_dialog_state.scroll_state.max_scroll_index = app_state.help_dialog_state.scroll_state.max_scroll_index =
(self.styled_help_text.len() as u16 (self.styled_help_text.len() as u16
+ (constants::HELP_TEXT.len() as u16 - 4) + (constants::HELP_TEXT.len() as u16 - 5)
+ overflow_buffer) + overflow_buffer)
.saturating_sub(draw_loc.height); .saturating_sub(draw_loc.height);

View File

@ -67,6 +67,7 @@ impl DiskTableWidget for Painter {
get_variable_intrinsic_widths(width as u16, &width_ratios, &DISK_HEADERS_LENS); get_variable_intrinsic_widths(width as u16, &width_ratios, &DISK_HEADERS_LENS);
let intrinsic_widths = &variable_intrinsic_results.0[0..variable_intrinsic_results.1]; let intrinsic_widths = &variable_intrinsic_results.0[0..variable_intrinsic_results.1];
// TODO: This seems to be bugged? The selected text style gets "stuck"? I think this gets fixed with tui 0.10?
let (border_and_title_style, highlight_style) = if is_on_widget { let (border_and_title_style, highlight_style) = if is_on_widget {
( (
self.colours.highlighted_border_style, self.colours.highlighted_border_style,

View File

@ -38,8 +38,6 @@ impl MemBasicWidget for Painter {
); );
} }
// +9 due to 3 + 4 + 2 + 2 columns for the name & space + percentage + bar bounds + margin spacing
let bar_length = usize::from(draw_loc.width.saturating_sub(11));
let ram_use_percentage = if let Some(mem) = mem_data.last() { let ram_use_percentage = if let Some(mem) = mem_data.last() {
mem.1 mem.1
} else { } else {
@ -50,20 +48,63 @@ impl MemBasicWidget for Painter {
} else { } else {
0.0 0.0
}; };
let num_bars_ram = calculate_basic_use_bars(ram_use_percentage, bar_length);
let num_bars_swap = calculate_basic_use_bars(swap_use_percentage, bar_length); // +7 due to 3 + 2 + 2 columns for the name & space + bar bounds + margin spacing
let mem_label = format!( // Then + length of fraction
let ram_bar_length = usize::from(
draw_loc
.width
.saturating_sub(7)
.saturating_sub(app_state.canvas_data.mem_label_frac.trim().len() as u16),
);
let swap_bar_length = usize::from(
draw_loc
.width
.saturating_sub(7)
.saturating_sub(app_state.canvas_data.swap_label_frac.trim().len() as u16),
);
let num_bars_ram = calculate_basic_use_bars(ram_use_percentage, ram_bar_length);
let num_bars_swap = calculate_basic_use_bars(swap_use_percentage, swap_bar_length);
// TODO: Use different styling for the frac.
let mem_label = if app_state.basic_mode_use_percent {
format!(
"RAM[{}{}{:3.0}%]\n", "RAM[{}{}{:3.0}%]\n",
"|".repeat(num_bars_ram), "|".repeat(num_bars_ram),
" ".repeat(bar_length - num_bars_ram), " ".repeat(
ram_use_percentage.round(), ram_bar_length - num_bars_ram
); + app_state.canvas_data.mem_label_frac.trim().len()
let swap_label = format!( - 4
),
ram_use_percentage.round()
)
} else {
format!(
"RAM[{}{}{}]\n",
"|".repeat(num_bars_ram),
" ".repeat(ram_bar_length - num_bars_ram),
&app_state.canvas_data.mem_label_frac.trim()
)
};
let swap_label = if app_state.basic_mode_use_percent {
format!(
"SWP[{}{}{:3.0}%]", "SWP[{}{}{:3.0}%]",
"|".repeat(num_bars_swap), "|".repeat(num_bars_swap),
" ".repeat(bar_length - num_bars_swap), " ".repeat(
swap_use_percentage.round(), swap_bar_length - num_bars_swap
); + app_state.canvas_data.swap_label_frac.trim().len()
- 4
),
swap_use_percentage.round()
)
} else {
format!(
"SWP[{}{}{}]",
"|".repeat(num_bars_swap),
" ".repeat(swap_bar_length - num_bars_swap),
&app_state.canvas_data.swap_label_frac.trim()
)
};
let mem_text = [ let mem_text = [
Text::styled(mem_label, self.colours.ram_style), Text::styled(mem_label, self.colours.ram_style),

View File

@ -62,10 +62,13 @@ impl MemGraphWidget for Painter {
.labels_style(self.colours.graph_style); .labels_style(self.colours.graph_style);
let mut mem_canvas_vec: Vec<Dataset<'_>> = vec![]; let mut mem_canvas_vec: Vec<Dataset<'_>> = vec![];
let mem_label = format!(
"RAM:{}{}",
app_state.canvas_data.mem_label_percent, app_state.canvas_data.mem_label_frac
);
mem_canvas_vec.push( mem_canvas_vec.push(
Dataset::default() Dataset::default()
.name(&app_state.canvas_data.mem_label) .name(&mem_label)
.marker(if app_state.app_config_fields.use_dot { .marker(if app_state.app_config_fields.use_dot {
Marker::Dot Marker::Dot
} else { } else {
@ -76,9 +79,13 @@ impl MemGraphWidget for Painter {
.graph_type(tui::widgets::GraphType::Line), .graph_type(tui::widgets::GraphType::Line),
); );
let swap_label = format!(
"SWP:{}{}",
app_state.canvas_data.swap_label_percent, app_state.canvas_data.swap_label_frac
);
mem_canvas_vec.push( mem_canvas_vec.push(
Dataset::default() Dataset::default()
.name(&app_state.canvas_data.swap_label) .name(&swap_label)
.marker(if app_state.app_config_fields.use_dot { .marker(if app_state.app_config_fields.use_dot {
Marker::Dot Marker::Dot
} else { } else {

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
app::App, app::{data_harvester::processes::ProcessSorting, App},
canvas::{ canvas::{
drawing_utils::{ drawing_utils::{
get_search_start_position, get_start_position, get_variable_intrinsic_widths, get_search_start_position, get_start_position, get_variable_intrinsic_widths,
@ -152,6 +152,7 @@ impl ProcessTableWidget for Painter {
// Draw! // Draw!
let is_proc_widget_grouped = proc_widget_state.is_grouped; let is_proc_widget_grouped = proc_widget_state.is_grouped;
let mem_enabled = proc_widget_state.columns.is_enabled(&ProcessSorting::Mem);
let process_rows = sliced_vec.iter().map(|process| { let process_rows = sliced_vec.iter().map(|process| {
Row::Data( Row::Data(
vec![ vec![
@ -161,8 +162,12 @@ impl ProcessTableWidget for Painter {
process.pid.to_string() process.pid.to_string()
}, },
process.name.clone(), process.name.clone(),
format!("{:.1}%", process.cpu_usage), format!("{:.1}%", process.cpu_percent_usage),
format!("{:.1}%", process.mem_usage), if mem_enabled {
format!("{:.0}{}", process.mem_usage_str.0, process.mem_usage_str.1)
} else {
format!("{:.1}%", process.mem_percent_usage)
},
process.read_per_sec.to_string(), process.read_per_sec.to_string(),
process.write_per_sec.to_string(), process.write_per_sec.to_string(),
process.total_read.to_string(), process.total_read.to_string(),

View File

@ -42,14 +42,15 @@ lazy_static! {
} }
// Help text // Help text
pub const HELP_CONTENTS_TEXT: [&str; 7] = [ pub const HELP_CONTENTS_TEXT: [&str; 8] = [
"Press the corresponding numbers to jump to the section, or scroll:\n", "Press the corresponding numbers to jump to the section, or scroll:\n",
"1 - General\n", "1 - General\n",
"2 - CPU widget\n", "2 - CPU widget\n",
"3 - Process widget\n", "3 - Process widget\n",
"4 - Process search widget\n", "4 - Process search widget\n",
"5 - Process sort widget\n", "5 - Process sort widget\n",
"6 - Battery widget", "6 - Battery widget\n",
"7 - Basic memory widget",
]; ];
pub const GENERAL_HELP_TEXT: [&str; 29] = [ pub const GENERAL_HELP_TEXT: [&str; 29] = [
@ -91,7 +92,7 @@ pub const CPU_HELP_TEXT: [&str; 2] = [
// TODO [Help]: Search in help? // TODO [Help]: Search in help?
// TODO [Help]: Move to using tables for easier formatting? // TODO [Help]: Move to using tables for easier formatting?
pub const PROCESS_HELP_TEXT: [&str; 11] = [ pub const PROCESS_HELP_TEXT: [&str; 12] = [
"3 - Process widget\n", "3 - Process widget\n",
"dd Kill the selected process\n", "dd Kill the selected process\n",
"c Sort by CPU usage, press again to reverse sorting order\n", "c Sort by CPU usage, press again to reverse sorting order\n",
@ -102,7 +103,8 @@ pub const PROCESS_HELP_TEXT: [&str; 11] = [
"Ctrl-f, / Open process search widget\n", "Ctrl-f, / Open process search widget\n",
"P Toggle between showing the full path or just the process name\n", "P Toggle between showing the full path or just the process name\n",
"s, F6 Open process sort widget\n", "s, F6 Open process sort widget\n",
"I Invert current sort", "I Invert current sort\n",
"% Toggle between values and percentages for memory usage",
]; ];
pub const SEARCH_HELP_TEXT: [&str; 43] = [ pub const SEARCH_HELP_TEXT: [&str; 43] = [
@ -166,6 +168,11 @@ pub const BATTERY_HELP_TEXT: [&str; 3] = [
"Right Go to next battery", "Right Go to next battery",
]; ];
pub const BASIC_MEM_HELP_TEXT: [&str; 2] = [
"7 - Basic memory widget\n",
"% Toggle between values and percentages for memory usage",
];
lazy_static! { lazy_static! {
pub static ref HELP_TEXT: Vec<Vec<&'static str>> = vec![ pub static ref HELP_TEXT: Vec<Vec<&'static str>> = vec![
HELP_CONTENTS_TEXT.to_vec(), HELP_CONTENTS_TEXT.to_vec(),
@ -175,6 +182,7 @@ lazy_static! {
SEARCH_HELP_TEXT.to_vec(), SEARCH_HELP_TEXT.to_vec(),
SORT_HELP_TEXT.to_vec(), SORT_HELP_TEXT.to_vec(),
BATTERY_HELP_TEXT.to_vec(), BATTERY_HELP_TEXT.to_vec(),
BASIC_MEM_HELP_TEXT.to_vec(),
]; ];
} }

View File

@ -34,8 +34,10 @@ pub struct ConvertedNetworkData {
pub struct ConvertedProcessData { pub struct ConvertedProcessData {
pub pid: u32, pub pid: u32,
pub name: String, pub name: String,
pub cpu_usage: f64, pub cpu_percent_usage: f64,
pub mem_usage: f64, pub mem_percent_usage: f64,
pub mem_usage_kb: u64,
pub mem_usage_str: (f64, String),
pub group_pids: Vec<u32>, pub group_pids: Vec<u32>,
pub read_per_sec: String, pub read_per_sec: String,
pub write_per_sec: String, pub write_per_sec: String,
@ -51,8 +53,9 @@ pub struct ConvertedProcessData {
#[derive(Clone, Default, Debug)] #[derive(Clone, Default, Debug)]
pub struct SingleProcessData { pub struct SingleProcessData {
pub pid: u32, pub pid: u32,
pub cpu_usage: f64, pub cpu_percent_usage: f64,
pub mem_usage: f64, pub mem_percent_usage: f64,
pub mem_usage_kb: u64,
pub group_pids: Vec<u32>, pub group_pids: Vec<u32>,
pub read_per_sec: u64, pub read_per_sec: u64,
pub write_per_sec: u64, pub write_per_sec: u64,
@ -231,9 +234,11 @@ pub fn convert_swap_data_points(
result result
} }
pub fn convert_mem_labels(current_data: &data_farmer::DataCollection) -> (String, String) { pub fn convert_mem_labels(
let mem_label = "RAM:".to_string() current_data: &data_farmer::DataCollection,
+ &format!( ) -> (String, String, String, String) {
(
format!(
"{:3.0}%", "{:3.0}%",
match current_data.memory_harvest.mem_total_in_mb { match current_data.memory_harvest.mem_total_in_mb {
0 => 0.0, 0 => 0.0,
@ -241,15 +246,13 @@ pub fn convert_mem_labels(current_data: &data_farmer::DataCollection) -> (String
current_data.memory_harvest.mem_used_in_mb as f64 * 100.0 current_data.memory_harvest.mem_used_in_mb as f64 * 100.0
/ current_data.memory_harvest.mem_total_in_mb as f64, / current_data.memory_harvest.mem_total_in_mb as f64,
} }
) ),
+ &format!( format!(
" {:.1}GB/{:.1}GB", " {:.1}GB/{:.1}GB",
current_data.memory_harvest.mem_used_in_mb as f64 / 1024.0, current_data.memory_harvest.mem_used_in_mb as f64 / 1024.0,
(current_data.memory_harvest.mem_total_in_mb as f64 / 1024.0) (current_data.memory_harvest.mem_total_in_mb as f64 / 1024.0)
); ),
format!(
let swap_label = "SWP:".to_string()
+ &format!(
"{:3.0}%", "{:3.0}%",
match current_data.swap_harvest.mem_total_in_mb { match current_data.swap_harvest.mem_total_in_mb {
0 => 0.0, 0 => 0.0,
@ -257,14 +260,13 @@ pub fn convert_mem_labels(current_data: &data_farmer::DataCollection) -> (String
current_data.swap_harvest.mem_used_in_mb as f64 * 100.0 current_data.swap_harvest.mem_used_in_mb as f64 * 100.0
/ current_data.swap_harvest.mem_total_in_mb as f64, / current_data.swap_harvest.mem_total_in_mb as f64,
} }
) ),
+ &format!( format!(
" {:.1}GB/{:.1}GB", " {:.1}GB/{:.1}GB",
current_data.swap_harvest.mem_used_in_mb as f64 / 1024.0, current_data.swap_harvest.mem_used_in_mb as f64 / 1024.0,
(current_data.swap_harvest.mem_total_in_mb as f64 / 1024.0) (current_data.swap_harvest.mem_total_in_mb as f64 / 1024.0)
); ),
)
(mem_label, swap_label)
} }
pub fn get_rx_tx_data_points( pub fn get_rx_tx_data_points(
@ -398,8 +400,10 @@ pub fn convert_process_data(
ProcessNamingType::Name => process.name.to_string(), ProcessNamingType::Name => process.name.to_string(),
ProcessNamingType::Path => process.path.to_string(), ProcessNamingType::Path => process.path.to_string(),
}, },
cpu_usage: process.cpu_usage_percent, cpu_percent_usage: process.cpu_usage_percent,
mem_usage: process.mem_usage_percent, mem_percent_usage: process.mem_usage_percent,
mem_usage_kb: process.mem_usage_kb,
mem_usage_str: get_exact_byte_values(process.mem_usage_kb * 1024, false),
group_pids: vec![process.pid], group_pids: vec![process.pid],
read_per_sec, read_per_sec,
write_per_sec, write_per_sec,
@ -428,8 +432,9 @@ pub fn convert_process_data(
..SingleProcessData::default() ..SingleProcessData::default()
}); });
(*entry).cpu_usage += process.cpu_usage_percent; (*entry).cpu_percent_usage += process.cpu_usage_percent;
(*entry).mem_usage += process.mem_usage_percent; (*entry).mem_percent_usage += process.mem_usage_percent;
(*entry).mem_usage_kb += process.mem_usage_kb;
(*entry).group_pids.push(process.pid); (*entry).group_pids.push(process.pid);
(*entry).read_per_sec += process.read_bytes_per_sec; (*entry).read_per_sec += process.read_bytes_per_sec;
(*entry).write_per_sec += process.write_bytes_per_sec; (*entry).write_per_sec += process.write_bytes_per_sec;
@ -458,8 +463,10 @@ pub fn convert_process_data(
ConvertedProcessData { ConvertedProcessData {
pid: p.pid, pid: p.pid,
name: identifier.to_string(), name: identifier.to_string(),
cpu_usage: p.cpu_usage, cpu_percent_usage: p.cpu_percent_usage,
mem_usage: p.mem_usage, mem_percent_usage: p.mem_percent_usage,
mem_usage_kb: p.mem_usage_kb,
mem_usage_str: get_exact_byte_values(p.mem_usage_kb * 1024, false),
group_pids: p.group_pids, group_pids: p.group_pids,
read_per_sec, read_per_sec,
write_per_sec, write_per_sec,

View File

@ -213,8 +213,10 @@ fn main() -> error::Result<()> {
app.canvas_data.swap_data = app.canvas_data.swap_data =
convert_swap_data_points(&app.data_collection, false); convert_swap_data_points(&app.data_collection, false);
let memory_and_swap_labels = convert_mem_labels(&app.data_collection); let memory_and_swap_labels = convert_mem_labels(&app.data_collection);
app.canvas_data.mem_label = memory_and_swap_labels.0; app.canvas_data.mem_label_percent = memory_and_swap_labels.0;
app.canvas_data.swap_label = memory_and_swap_labels.1; app.canvas_data.mem_label_frac = memory_and_swap_labels.1;
app.canvas_data.swap_label_percent = memory_and_swap_labels.2;
app.canvas_data.swap_label_frac = memory_and_swap_labels.3;
} }
if app.used_widgets.use_cpu { if app.used_widgets.use_cpu {
@ -668,20 +670,26 @@ fn sort_process_data(
ProcessSorting::CpuPercent => { ProcessSorting::CpuPercent => {
to_sort_vec.sort_by(|a, b| { to_sort_vec.sort_by(|a, b| {
utils::gen_util::get_ordering( utils::gen_util::get_ordering(
a.cpu_usage, a.cpu_percent_usage,
b.cpu_usage, b.cpu_percent_usage,
proc_widget_state.process_sorting_reverse, proc_widget_state.process_sorting_reverse,
) )
}); });
} }
ProcessSorting::Mem => { ProcessSorting::Mem => {
// TODO: Do when I do mem values in processes to_sort_vec.sort_by(|a, b| {
utils::gen_util::get_ordering(
a.mem_usage_kb,
b.mem_usage_kb,
proc_widget_state.process_sorting_reverse,
)
});
} }
ProcessSorting::MemPercent => { ProcessSorting::MemPercent => {
to_sort_vec.sort_by(|a, b| { to_sort_vec.sort_by(|a, b| {
utils::gen_util::get_ordering( utils::gen_util::get_ordering(
a.mem_usage, a.mem_percent_usage,
b.mem_usage, b.mem_percent_usage,
proc_widget_state.process_sorting_reverse, proc_widget_state.process_sorting_reverse,
) )
}); });