summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2020-04-04 18:29:32 -0400
committerGitHub <noreply@github.com>2020-04-04 18:29:32 -0400
commitba0fbf808e4d04405d704bf2a1b071b792d135d5 (patch)
treea76b3c2ab8b4ddac51d1d71a2688babfc932fc0f
parent620d614f1274429ca8e579bd2b9f9e8090f720d9 (diff)
(perf) Avoid harvesting if widget is not being displayed
-rw-r--r--README.md2
-rw-r--r--src/app.rs1
-rw-r--r--src/app/data_harvester.rs120
-rw-r--r--src/app/data_harvester/disks.rs20
-rw-r--r--src/app/data_harvester/mem.rs24
-rw-r--r--src/app/data_harvester/network.rs12
-rw-r--r--src/app/data_harvester/temperature.rs10
-rw-r--r--src/app/layout_manager.rs12
-rw-r--r--src/main.rs86
-rw-r--r--src/options.rs21
10 files changed, 210 insertions, 98 deletions
diff --git a/README.md b/README.md
index e6b8cb78..560ed2b6 100644
--- a/README.md
+++ b/README.md
@@ -213,7 +213,7 @@ searching by PID and by process name.
### Zoom
-Using the +/- keys or the scroll wheel will move adjust the current time intervals of the currently selected widget. Widgets
+Using the `+`/`-` keys or the scroll wheel will move adjust the current time intervals of the currently selected widget. Widgets
can hold different time intervals independently.
### Maximizing
diff --git a/src/app.rs b/src/app.rs
index ba2186a4..8f495afd 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -512,6 +512,7 @@ pub struct App {
pub app_config_fields: AppConfigFields,
pub widget_map: HashMap<u64, BottomWidget>,
pub current_widget: BottomWidget,
+ pub used_widgets: UsedWidgets,
}
impl App {
diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs
index e4b59970..a0c7c955 100644
--- a/src/app/data_harvester.rs
+++ b/src/app/data_harvester.rs
@@ -4,6 +4,8 @@ use std::{collections::HashMap, time::Instant};
use sysinfo::{System, SystemExt};
+use crate::app::layout_manager::UsedWidgets;
+
use futures::join;
pub mod cpu;
@@ -56,7 +58,7 @@ impl Data {
}
}
-pub struct DataState {
+pub struct DataCollector {
pub data: Data,
sys: System,
prev_pid_stats: HashMap<String, (f64, Instant)>,
@@ -69,11 +71,12 @@ pub struct DataState {
total_rx: u64,
total_tx: u64,
show_average_cpu: bool,
+ widgets_to_harvest: UsedWidgets,
}
-impl Default for DataState {
+impl Default for DataCollector {
fn default() -> Self {
- DataState {
+ DataCollector {
data: Data::default(),
sys: System::new_all(),
prev_pid_stats: HashMap::new(),
@@ -86,11 +89,23 @@ impl Default for DataState {
total_rx: 0,
total_tx: 0,
show_average_cpu: false,
+ widgets_to_harvest: UsedWidgets::default(),
}
}
}
-impl DataState {
+impl DataCollector {
+ pub fn init(&mut self) {
+ self.mem_total_kb = self.sys.get_total_memory();
+ futures::executor::block_on(self.update_data());
+ std::thread::sleep(std::time::Duration::from_millis(250));
+ self.data.first_run_cleanup();
+ }
+
+ pub fn set_collected_data(&mut self, used_widgets: UsedWidgets) {
+ self.widgets_to_harvest = used_widgets;
+ }
+
pub fn set_temperature_type(&mut self, temperature_type: temperature::TemperatureType) {
self.temperature_type = temperature_type;
}
@@ -103,42 +118,45 @@ impl DataState {
self.show_average_cpu = show_average_cpu;
}
- pub fn init(&mut self) {
- self.mem_total_kb = self.sys.get_total_memory();
- futures::executor::block_on(self.update_data());
- std::thread::sleep(std::time::Duration::from_millis(250));
- self.data.first_run_cleanup();
- }
-
pub async fn update_data(&mut self) {
- self.sys.refresh_system();
+ if self.widgets_to_harvest.use_cpu {
+ self.sys.refresh_cpu();
+ }
if cfg!(not(target_os = "linux")) {
- self.sys.refresh_processes();
- self.sys.refresh_components();
+ if self.widgets_to_harvest.use_proc {
+ self.sys.refresh_processes();
+ }
+ if self.widgets_to_harvest.use_temp {
+ self.sys.refresh_components();
+ }
}
- if cfg!(target_os = "windows") {
+ if cfg!(target_os = "windows") && self.widgets_to_harvest.use_net {
self.sys.refresh_networks();
}
let current_instant = std::time::Instant::now();
// CPU
- self.data.cpu = cpu::get_cpu_data_list(&self.sys, self.show_average_cpu);
+ if self.widgets_to_harvest.use_cpu {
+ self.data.cpu = cpu::get_cpu_data_list(&self.sys, self.show_average_cpu);
+ }
- // Processes. This is the longest part of the harvesting process... changing this might be
- // good in the future. What was tried already:
- // * Splitting the internal part into multiple scoped threads (dropped by ~.01 seconds, but upped usage)
- if let Ok(process_list) = 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,
- self.mem_total_kb,
- current_instant,
- ) {
- self.data.list_of_processes = process_list;
+ if self.widgets_to_harvest.use_proc {
+ // Processes. This is the longest part of the harvesting process... changing this might be
+ // good in the future. What was tried already:
+ // * Splitting the internal part into multiple scoped threads (dropped by ~.01 seconds, but upped usage)
+ if let Ok(process_list) = 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,
+ self.mem_total_kb,
+ current_instant,
+ ) {
+ self.data.list_of_processes = process_list;
+ }
}
// ASYNC
@@ -148,13 +166,18 @@ impl DataState {
&mut self.total_rx,
&mut self.total_tx,
current_instant,
+ self.widgets_to_harvest.use_net,
);
- let mem_data_fut = mem::get_mem_data_list();
- let swap_data_fut = mem::get_swap_data_list();
- let disk_data_fut = disks::get_disk_usage_list();
- let disk_io_usage_fut = disks::get_io_usage_list(false);
- let temp_data_fut = temperature::get_temperature_data(&self.sys, &self.temperature_type);
+ let mem_data_fut = mem::get_mem_data_list(self.widgets_to_harvest.use_mem);
+ let swap_data_fut = mem::get_swap_data_list(self.widgets_to_harvest.use_mem);
+ let disk_data_fut = disks::get_disk_usage_list(self.widgets_to_harvest.use_disk);
+ let disk_io_usage_fut = disks::get_io_usage_list(false, self.widgets_to_harvest.use_disk);
+ let temp_data_fut = temperature::get_temperature_data(
+ &self.sys,
+ &self.temperature_type,
+ self.widgets_to_harvest.use_temp,
+ );
let (net_data, mem_res, swap_res, disk_res, io_res, temp_res) = join!(
network_data_fut,
@@ -166,27 +189,40 @@ impl DataState {
);
// After async
- self.data.network = net_data;
- self.total_rx = self.data.network.total_rx;
- self.total_tx = self.data.network.total_tx;
+ if let Some(net_data) = net_data {
+ self.data.network = net_data;
+ self.total_rx = self.data.network.total_rx;
+ self.total_tx = self.data.network.total_tx;
+ }
if let Ok(memory) = mem_res {
- self.data.memory = memory;
+ if let Some(memory) = memory {
+ self.data.memory = memory;
+ }
}
if let Ok(swap) = swap_res {
- self.data.swap = swap;
+ if let Some(swap) = swap {
+ self.data.swap = swap;
+ }
}
if let Ok(disks) = disk_res {
- self.data.disks = disks;
+ if let Some(disks) = disks {
+ self.data.disks = disks;
+ }
}
+
if let Ok(io) = io_res {
- self.data.io = io;
+ if let Some(io) = io {
+ self.data.io = io;
+ }
}
if let Ok(temp) = temp_res {
- self.data.temperature_sensors = temp;
+ if let Some(temp) = temp {
+ self.data.temperature_sensors = temp;
+ }
}
// Update time
diff --git a/src/app/data_harvester/disks.rs b/src/app/data_harvester/disks.rs
index e8401645..93720975 100644
--- a/src/app/data_harvester/disks.rs
+++ b/src/app/data_harvester/disks.rs
@@ -18,7 +18,13 @@ pub struct IOData {
pub type IOHarvest = std::collections::HashMap<String, IOData>;
-pub async fn get_io_usage_list(get_physical: bool) -> crate::utils::error::Result<IOHarvest> {
+pub async fn get_io_usage_list(
+ get_physical: bool, actually_get: bool,
+) -> crate::utils::error::Result<Option<IOHarvest>> {
+ if !actually_get {
+ return Ok(None);
+ }
+
let mut io_hash: std::collections::HashMap<String, IOData> = std::collections::HashMap::new();
if get_physical {
let mut physical_counter_stream = heim::disk::io_counters_physical();
@@ -48,10 +54,16 @@ pub async fn get_io_usage_list(get_physical: bool) -> crate::utils::error::Resul
}
}
- Ok(io_hash)
+ Ok(Some(io_hash))
}
-pub async fn get_disk_usage_list() -> crate::utils::error::Result<Vec<DiskHarvest>> {
+pub async fn get_disk_usage_list(
+ actually_get: bool,
+) -> crate::utils::error::Result<Option<Vec<DiskHarvest>>> {
+ if !actually_get {
+ return Ok(None);
+ }
+
let mut vec_disks: Vec<DiskHarvest> = Vec::new();
let mut partitions_stream = heim::disk::partitions_physical();
@@ -81,5 +93,5 @@ pub async fn get_disk_usage_list() -> crate::utils::error::Result<Vec<DiskHarves
vec_disks.sort_by(|a, b| a.name.cmp(&b.name));
- Ok(vec_disks)
+ Ok(Some(vec_disks))
}
diff --git a/src/app/data_harvester/mem.rs b/src/app/data_harvester/mem.rs
index d9a9993a..12ac1ecf 100644
--- a/src/app/data_harvester/mem.rs
+++ b/src/app/data_harvester/mem.rs
@@ -15,21 +15,33 @@ impl Default for MemHarvest {
}
}
-pub async fn get_mem_data_list() -> crate::utils::error::Result<MemHarvest> {
+pub async fn get_mem_data_list(
+ actually_get: bool,
+) -> crate::utils::error::Result<Option<MemHarvest>> {
+ if !actually_get {
+ return Ok(None);
+ }
+
let memory = heim::memory::memory().await?;
- Ok(MemHarvest {
+ Ok(Some(MemHarvest {
mem_total_in_mb: memory.total().get::<information::megabyte>(),
mem_used_in_mb: memory.total().get::<information::megabyte>()
- memory.available().get::<information::megabyte>(),
- })
+ }))
}
-pub async fn get_swap_data_list() -> crate::utils::error::Result<MemHarvest> {
+pub async fn get_swap_data_list(
+ actually_get: bool,
+) -> crate::utils::error::Result<Option<MemHarvest>> {
+ if !actually_get {
+ return Ok(None);
+ }
+
let memory = heim::memory::swap().await?;
- Ok(MemHarvest {
+ Ok(Some(MemHarvest {
mem_total_in_mb: memory.total().get::<information::megabyte>(),
mem_used_in_mb: memory.used().get::<information::megabyte>(),
- })
+ }))
}
diff --git a/src/app/data_harvester/network.rs b/src/app/data_harvester/network.rs
index c425ccd6..5e50a110 100644
--- a/src/app/data_harvester/network.rs
+++ b/src/app/data_harvester/network.rs
@@ -22,8 +22,12 @@ impl NetworkHarvest {
pub async fn get_network_data(
sys: &System, prev_net_access_time: Instant, prev_net_rx: &mut u64, prev_net_tx: &mut u64,
- curr_time: Instant,
-) -> NetworkHarvest {
+ curr_time: Instant, actually_get: bool,
+) -> Option<NetworkHarvest> {
+ if !actually_get {
+ return None;
+ }
+
let mut io_data = net::io_counters();
let mut total_rx: u64 = 0;
let mut total_tx: u64 = 0;
@@ -56,10 +60,10 @@ pub async fn get_network_data(
*prev_net_rx = total_rx;
*prev_net_tx = total_tx;
- NetworkHarvest {
+ Some(NetworkHarvest {
rx,
tx,
total_rx,
total_tx,
- }
+ })
}
diff --git a/src/app/data_harvester/temperature.rs b/src/app/data_harvester/temperature.rs
index de3ce9d9..b0a39e3d 100644
--- a/src/app/data_harvester/temperature.rs
+++ b/src/app/data_harvester/temperature.rs
@@ -24,8 +24,12 @@ impl Default for TemperatureType {
}
pub async fn get_temperature_data(
- sys: &System, temp_type: &TemperatureType,
-) -> crate::utils::error::Result<Vec<TempHarvest>> {
+ sys: &System, temp_type: &TemperatureType, actually_get: bool,
+) -> crate::utils::error::Result<Option<Vec<TempHarvest>>> {
+ if !actually_get {
+ return Ok(None);
+ }
+
let mut temperature_vec: Vec<TempHarvest> = Vec::new();
if cfg!(target_os = "linux") {
@@ -86,7 +90,7 @@ pub async fn get_temperature_data(
.unwrap_or(Ordering::Equal)
});
- Ok(temperature_vec)
+ Ok(Some(temperature_vec))
}
fn convert_celsius_to_kelvin(celsius: f32) -> f32 {
diff --git a/src/app/layout_manager.rs b/src/app/layout_manager.rs
index 41ec72b6..522fcb4c 100644
--- a/src/app/layout_manager.rs
+++ b/src/app/layout_manager.rs
@@ -864,7 +864,7 @@ pub struct BottomWidget {
pub flex_grow: bool,
}
-#[derive(Debug, Clone, Eq, PartialEq)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum BottomWidgetType {
Empty,
Cpu,
@@ -938,3 +938,13 @@ impl std::str::FromStr for BottomWidgetType {
}
}
}
+
+#[derive(Clone, Default)]
+pub struct UsedWidgets {
+ pub use_cpu: bool,
+ pub use_mem: bool,
+ pub use_net: bool,
+ pub use_proc: bool,
+ pub use_disk: bool,
+ pub use_temp: bool,
+}
diff --git a/src/main.rs b/src/main.rs
index 5ffe5c86..a53408d6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -27,6 +27,7 @@ use tui::{backend::CrosstermBackend, Terminal};
use app::{
data_harvester::{self, processes::ProcessSorting},
+ layout_manager::UsedWidgets,
App,
};
use constants::*;
@@ -139,6 +140,7 @@ fn main() -> error::Result<()> {
app.app_config_fields.update_rate_in_milliseconds,
app.app_config_fields.temperature_type.clone(),
app.app_config_fields.show_average_cpu,
+ app.used_widgets.clone(),
);
let mut painter = canvas::Painter::init(widget_layout);
@@ -170,49 +172,62 @@ fn main() -> error::Result<()> {
// Convert all data into tui-compliant components
// Network
- let network_data = convert_network_data_points(&app.data_collection, false);
- app.canvas_data.network_data_rx = network_data.rx;
- app.canvas_data.network_data_tx = network_data.tx;
- app.canvas_data.rx_display = network_data.rx_display;
- app.canvas_data.tx_display = network_data.tx_display;
- app.canvas_data.total_rx_display = network_data.total_rx_display;
- app.canvas_data.total_tx_display = network_data.total_tx_display;
+ if app.used_widgets.use_net {
+ let network_data =
+ convert_network_data_points(&app.data_collection, false);
+ app.canvas_data.network_data_rx = network_data.rx;
+ app.canvas_data.network_data_tx = network_data.tx;
+ app.canvas_data.rx_display = network_data.rx_display;
+ app.canvas_data.tx_display = network_data.tx_display;
+ app.canvas_data.total_rx_display = network_data.total_rx_display;
+ app.canvas_data.total_tx_display = network_data.total_tx_display;
+ }
// Disk
- app.canvas_data.disk_data = convert_disk_row(&app.data_collection);
+ if app.used_widgets.use_disk {
+ app.canvas_data.disk_data = convert_disk_row(&app.data_collection);
+ }
// Temperatures
- app.canvas_data.temp_sensor_data = convert_temp_row(&app);
+ if app.used_widgets.use_temp {
+ app.canvas_data.temp_sensor_data = convert_temp_row(&app);
+ }
// Memory
- app.canvas_data.mem_data =
- convert_mem_data_points(&app.data_collection, false);
- app.canvas_data.swap_data =
- convert_swap_data_points(&app.data_collection, false);
- let memory_and_swap_labels = convert_mem_labels(&app.data_collection);
- app.canvas_data.mem_label = memory_and_swap_labels.0;
- app.canvas_data.swap_label = memory_and_swap_labels.1;
+ if app.used_widgets.use_mem {
+ app.canvas_data.mem_data =
+ convert_mem_data_points(&app.data_collection, false);
+ app.canvas_data.swap_data =
+ convert_swap_data_points(&app.data_collection, false);
+ let memory_and_swap_labels = convert_mem_labels(&app.data_collection);
+ app.canvas_data.mem_label = memory_and_swap_labels.0;
+ app.canvas_data.swap_label = memory_and_swap_labels.1;
+ }
// Pre-fill CPU if needed
- if first_run {
- let cpu_len = app.data_collection.cpu_harvest.len();
- app.cpu_state.widget_states.values_mut().for_each(|state| {
- state.core_show_vec = vec![true; cpu_len];
- state.num_cpus_shown = cpu_len;
- });
- app.cpu_state.num_cpus_total = cpu_len;
- first_run = false;
- }
+ if app.used_widgets.use_cpu {
+ if first_run {
+ let cpu_len = app.data_collection.cpu_harvest.len();
+ app.cpu_state.widget_states.values_mut().for_each(|state| {
+ state.core_show_vec = vec![true; cpu_len];
+ state.num_cpus_shown = cpu_len;
+ });
+ app.cpu_state.num_cpus_total = cpu_len;
+ first_run = false;
+ }
- // CPU
- app.canvas_data.cpu_data =
- convert_cpu_data_points(&app.data_collection, false);
+ // CPU
+ app.canvas_data.cpu_data =
+ convert_cpu_data_points(&app.data_collection, false);
+ }
// Processes
- let (single, grouped) = convert_process_data(&app.data_collection);
- app.canvas_data.process_data = single;
- app.canvas_data.grouped_process_data = grouped;
- update_all_process_lists(&mut app);
+ if app.used_widgets.use_proc {
+ let (single, grouped) = convert_process_data(&app.data_collection);
+ app.canvas_data.process_data = single;
+ app.canvas_data.grouped_process_data = grouped;
+ update_all_process_lists(&mut app);
+ }
}
}
BottomEvent::Clean => {
@@ -743,15 +758,16 @@ fn create_event_thread(
>,
rrx: std::sync::mpsc::Receiver<ResetEvent>, use_current_cpu_total: bool,
update_rate_in_milliseconds: u64, temp_type: data_harvester::temperature::TemperatureType,
- show_average_cpu: bool,
+ show_average_cpu: bool, used_widget_set: UsedWidgets,
) {
thread::spawn(move || {
let tx = tx.clone();
- let mut data_state = data_harvester::DataState::default();
- data_state.init();
+ let mut data_state = data_harvester::DataCollector::default();
+ data_state.set_collected_data(used_widget_set);
data_state.set_temperature_type(temp_type);
data_state.set_use_current_cpu_total(use_current_cpu_total);
data_state.set_show_average_cpu(show_average_cpu);
+ data_state.init();
loop {
if let Ok(message) = rrx.try_recv() {
match message {
diff --git a/src/options.rs b/src/options.rs
index 96e1e80a..3f5d9d2c 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -1,5 +1,5 @@
use serde::Deserialize;
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
use std::time::Instant;
use crate::{
@@ -100,6 +100,8 @@ pub fn build_app(
let mut initial_widget_type = BottomWidgetType::Proc;
let is_custom_layout = config.row.is_some();
+ let mut used_widget_set = HashSet::new();
+
for row in &widget_layout.rows {
for col in &row.children {
for col_row in &col.children {
@@ -135,6 +137,9 @@ pub fn build_app(
}
}
}
+
+ used_widget_set.insert(widget.widget_type.clone());
+
match widget.widget_type {
BottomWidgetType::Cpu => {
cpu_state_map.insert(
@@ -178,7 +183,6 @@ pub fn build_app(
}
}
- // FIXME: [MODULARITY] Don't collect if not added!
let basic_table_widget_state = if use_basic_mode {
Some(match initial_widget_type {
BottomWidgetType::Proc | BottomWidgetType::Disk | BottomWidgetType::Temp => {
@@ -213,6 +217,18 @@ pub fn build_app(
autohide_time,
};
+ let used_widgets = UsedWidgets {
+ use_cpu: used_widget_set.get(&BottomWidgetType::Cpu).is_some()
+ || used_widget_set.get(&BottomWidgetType::BasicCpu).is_some(),
+ use_mem: used_widget_set.get(&BottomWidgetType::Mem).is_some()
+ || used_widget_set.get(&BottomWidgetType::BasicMem).is_some(),
+ use_net: used_widget_set.get(&BottomWidgetType::Net).is_some()
+ || used_widget_set.get(&BottomWidgetType::BasicNet).is_some(),
+ use_proc: used_widget_set.get(&BottomWidgetType::Proc).is_some(),
+ use_disk: used_widget_set.get(&BottomWidgetType::Disk).is_some(),
+ use_temp: used_widget_set.get(&BottomWidgetType::Temp).is_some(),
+ };
+
Ok(App::builder()
.app_config_fields(app_config_fields)
.cpu_state(CpuState::init(cpu_state_map))
@@ -224,6 +240,7 @@ pub fn build_app(
.basic_table_widget_state(basic_table_widget_state)
.current_widget(widget_map.get(&initial_widget_id).unwrap().clone()) // I think the unwrap is fine here
.widget_map(widget_map)
+ .used_widgets(used_widgets)
.build())
}