From 4418f956c705848a224db05f7e389d1d2268c3f8 Mon Sep 17 00:00:00 2001 From: ClementTsang Date: Sat, 4 Jan 2020 19:20:54 -0500 Subject: [PATCH] Some cleaning up in the data_conversion area for cpu --- .vscode/settings.json | 68 +++++++++++++++++++++--------------------- README.md | 4 +++ src/canvas.rs | 43 ++++++++++++++++---------- src/data_conversion.rs | 62 ++++++++++++++++++++++++++------------ 4 files changed, 108 insertions(+), 69 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 1efd61f6..da1971ea 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,35 +1,35 @@ { - "cSpell.words": [ - "AHHHHHH", - "Dataset", - "Ryzen", - "Tebibyte", - "avgcpu", - "backend", - "crossterm", - "curr", - "datasets", - "dword", - "fract", - "gotop", - "gtop", - "heim", - "iowait", - "keybinds", - "macos", - "minwindef", - "noheader", - "ntdef", - "processthreadsapi", - "rustop", - "softirq", - "stime", - "sysinfo", - "termion", - "utime", - "vangelis", - "winapi", - "winnt" - ], - "cSpell.language": "en,en-GB" -} \ No newline at end of file + "cSpell.words": [ + "AHHHHHH", + "Dataset", + "Ryzen", + "Tebibyte", + "avgcpu", + "backend", + "crossterm", + "curr", + "datasets", + "dword", + "fract", + "gotop", + "gtop", + "heim", + "iowait", + "keybinds", + "macos", + "minwindef", + "noheader", + "ntdef", + "processthreadsapi", + "rustop", + "softirq", + "stime", + "sysinfo", + "termion", + "utime", + "vangelis", + "winapi", + "winnt" + ], + "cSpell.language": "en,en-GB" +} diff --git a/README.md b/README.md index 8c93f3b9..b95f0dac 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,10 @@ A graphical top clone, written in Rust. Inspired by both [gtop](https://github.c You can install by cloning and using `cargo build --release`, or use `cargo install bottom`. +#### Arch Linux + +You can get it from the AUR. + ### Windows You can currently install by cloning and building yourself using `cargo build --release`, or use `cargo install bottom` diff --git a/src/canvas.rs b/src/canvas.rs index 21ca88c7..09f84438 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -1,4 +1,8 @@ -use crate::{app, constants, data_conversion::ConvertedProcessData, utils::error, utils::gen_util::*}; +use crate::{ + app, constants, + data_conversion::{ConvertedCpuData, ConvertedProcessData}, + utils::{error, gen_util::*}, +}; use tui::{ backend, layout::{Alignment, Constraint, Direction, Layout, Rect}, @@ -50,7 +54,7 @@ pub struct CanvasData { pub memory_labels: Vec<(u64, u64)>, pub mem_data: Vec<(f64, f64)>, pub swap_data: Vec<(f64, f64)>, - pub cpu_data: Vec<(String, Vec<(f64, f64)>)>, + pub cpu_data: Vec, } /// Generates random colours. @@ -248,7 +252,7 @@ pub fn draw_data(terminal: &mut Terminal, app_state: &mu } fn draw_cpu_graph(f: &mut Frame, app_state: &app::App, draw_loc: Rect) { - let cpu_data: &[(String, Vec<(f64, f64)>)] = &app_state.canvas_data.cpu_data; + let cpu_data: &[ConvertedCpuData] = &app_state.canvas_data.cpu_data; // CPU usage graph let x_axis: Axis = Axis::default() @@ -260,6 +264,7 @@ fn draw_cpu_graph(f: &mut Frame, app_state: &app::App, d .labels(&["0%", "100%"]); let mut dataset_vector: Vec = Vec::new(); + let mut cpu_entries_vec: Vec<(Style, Vec<(f64, f64)>)> = Vec::new(); for (i, cpu) in cpu_data.iter().enumerate() { let mut avg_cpu_exist_offset = 0; @@ -272,21 +277,27 @@ fn draw_cpu_graph(f: &mut Frame, app_state: &app::App, d } } - dataset_vector.push( - Dataset::default() - .marker(if app_state.use_dot { Marker::Dot } else { Marker::Braille }) - .style(Style::default().fg(COLOUR_LIST[(i - avg_cpu_exist_offset) % COLOUR_LIST.len()])) - .data(&(cpu.1)), - ); + cpu_entries_vec.push(( + Style::default().fg(COLOUR_LIST[(i - avg_cpu_exist_offset) % COLOUR_LIST.len()]), + cpu.cpu_data.iter().map(<(f64, f64)>::from).collect::>(), + )); } - if !cpu_data.is_empty() && app_state.show_average_cpu { - // Unwrap should be safe here, this assumes that the cpu_data vector is populated... + if app_state.show_average_cpu { + if let Some(avg_cpu_entry) = cpu_data.first() { + cpu_entries_vec.push(( + Style::default().fg(COLOUR_LIST[(cpu_data.len() - 1) % COLOUR_LIST.len()]), + avg_cpu_entry.cpu_data.iter().map(<(f64, f64)>::from).collect::>(), + )); + } + } + + for cpu_entry in &cpu_entries_vec { dataset_vector.push( Dataset::default() .marker(if app_state.use_dot { Marker::Dot } else { Marker::Braille }) - .style(Style::default().fg(COLOUR_LIST[(cpu_data.len() - 1) % COLOUR_LIST.len()])) - .data(&(cpu_data.first().unwrap().1)), + .style(cpu_entry.0) + .data(&(cpu_entry.1)), ); } @@ -307,7 +318,7 @@ fn draw_cpu_graph(f: &mut Frame, app_state: &app::App, d } fn draw_cpu_legend(f: &mut Frame, app_state: &mut app::App, draw_loc: Rect) { - let cpu_data: &[(String, Vec<(f64, f64)>)] = &(app_state.canvas_data.cpu_data); + let cpu_data: &[ConvertedCpuData] = &(app_state.canvas_data.cpu_data); let num_rows = i64::from(draw_loc.height) - 4; let start_position = get_start_position( @@ -321,8 +332,8 @@ fn draw_cpu_legend(f: &mut Frame, app_state: &mut app::A let mut stringified_cpu_data: Vec> = Vec::new(); for cpu in sliced_cpu_data { - if let Some(cpu_data) = cpu.1.last() { - stringified_cpu_data.push(vec![cpu.0.clone(), format!("{:.0}%", cpu_data.1.round())]); + if let Some(cpu_data) = cpu.cpu_data.last() { + stringified_cpu_data.push(vec![cpu.cpu_name.clone(), format!("{:.0}%", cpu_data.usage.round())]); } } diff --git a/src/data_conversion.rs b/src/data_conversion.rs index 7bf688f8..e916faf0 100644 --- a/src/data_conversion.rs +++ b/src/data_conversion.rs @@ -23,6 +23,32 @@ pub struct ConvertedProcessData { pub mem_usage: String, } +#[derive(Clone, Default, Debug)] +pub struct ConvertedCpuData { + pub cpu_name: String, + pub cpu_data: Vec, +} + +#[derive(Clone, Default, Debug)] +pub struct CpuPoint { + pub time: f64, + pub usage: f64, +} + +impl From for (f64, f64) { + fn from(c: CpuPoint) -> (f64, f64) { + let CpuPoint { time, usage } = c; + (time, usage) + } +} + +impl From<&CpuPoint> for (f64, f64) { + fn from(c: &CpuPoint) -> (f64, f64) { + let CpuPoint { time, usage } = c; + (*time, *usage) + } +} + pub fn update_temp_row(app_data: &data_collection::Data, temp_type: &data_collection::temperature::TemperatureType) -> Vec> { let mut sensor_vector: Vec> = Vec::new(); @@ -121,33 +147,31 @@ pub fn update_process_row(app_data: &data_collection::Data) -> Vec Vec<(String, Vec<(f64, f64)>)> { - let mut cpu_data_vector: Vec<(String, Vec<(f64, f64)>)> = Vec::new(); - let mut cpu_collection: Vec> = Vec::new(); +pub fn update_cpu_data_points(show_avg_cpu: bool, app_data: &data_collection::Data) -> Vec { + let mut cpu_data_vector: Vec = Vec::new(); + let mut cpu_collection: Vec> = Vec::new(); if !app_data.list_of_cpu_packages.is_empty() { // I'm sorry for the following if statement but I couldn't be bothered here... for cpu_num in (if show_avg_cpu { 0 } else { 1 })..app_data.list_of_cpu_packages.last().unwrap().cpu_vec.len() { - let mut this_cpu_data: Vec<(f64, f64)> = Vec::new(); + let mut this_cpu_data: Vec = Vec::new(); for data in &app_data.list_of_cpu_packages { let current_time = std::time::Instant::now(); let current_cpu_usage = data.cpu_vec[cpu_num].cpu_usage; - let new_entry = ( - ((TIME_STARTS_FROM as f64 - current_time.duration_since(data.instant).as_millis() as f64) * 10_f64).floor(), - current_cpu_usage, - ); + let new_entry = CpuPoint { + time: ((TIME_STARTS_FROM as f64 - current_time.duration_since(data.instant).as_millis() as f64) * 10_f64).floor(), + usage: current_cpu_usage, + }; // Now, inject our joining points... - if !this_cpu_data.is_empty() { - let previous_element_data = *(this_cpu_data.last().unwrap()); + if let Some(previous_element_data) = this_cpu_data.last().cloned() { for idx in 0..50 { - this_cpu_data.push(( - previous_element_data.0 + ((new_entry.0 - previous_element_data.0) / 50.0 * f64::from(idx)), - previous_element_data.1 + ((new_entry.1 - previous_element_data.1) / 50.0 * f64::from(idx)), - )); + this_cpu_data.push(CpuPoint { + time: previous_element_data.time + ((new_entry.time - previous_element_data.time) / 50.0 * f64::from(idx)), + usage: previous_element_data.usage + ((new_entry.usage - previous_element_data.usage) / 50.0 * f64::from(idx)), + }); } } @@ -170,8 +194,8 @@ pub fn update_cpu_data_points(show_avg_cpu: bool, app_data: &data_collection::Da // .to_uppercase() + &format!("{:3}%", (data.last().unwrap_or(&(0_f64, 0_f64)).1.round() as u64)), // data.clone(), // )) - cpu_data_vector.push(( - format!( + cpu_data_vector.push(ConvertedCpuData { + cpu_name: format!( "{} ", if show_avg_cpu && i == 0 { "AVG" @@ -180,8 +204,8 @@ pub fn update_cpu_data_points(show_avg_cpu: bool, app_data: &data_collection::Da } ) .to_uppercase(), - data.clone(), - )); + cpu_data: data.clone(), + }); } } }