mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-22 21:24:49 +02:00
Slightly optimized how networking is... I think.
This commit is contained in:
parent
f04ff034f4
commit
e356b94867
@ -23,7 +23,7 @@ fn push_if_valid<T: std::clone::Clone>(result: &Result<T>, vector_to_push: &mut
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
pub list_of_cpu_packages: Vec<cpu::CPUPackage>,
|
pub list_of_cpu_packages: Vec<cpu::CPUPackage>,
|
||||||
pub list_of_io: Vec<disks::IOPackage>,
|
pub list_of_io: Vec<disks::IOPackage>,
|
||||||
@ -31,10 +31,10 @@ pub struct Data {
|
|||||||
pub memory: Vec<mem::MemData>,
|
pub memory: Vec<mem::MemData>,
|
||||||
pub swap: Vec<mem::MemData>,
|
pub swap: Vec<mem::MemData>,
|
||||||
pub list_of_temperature_sensor: Vec<temperature::TempData>,
|
pub list_of_temperature_sensor: Vec<temperature::TempData>,
|
||||||
pub network: Vec<network::NetworkData>,
|
pub network: network::NetworkStorage,
|
||||||
pub list_of_processes: Vec<processes::ProcessData>,
|
pub list_of_processes: Vec<processes::ProcessData>,
|
||||||
pub grouped_list_of_processes: Option<Vec<processes::ProcessData>>,
|
pub grouped_list_of_processes: Option<Vec<processes::ProcessData>>,
|
||||||
pub list_of_disks: Vec<disks::DiskData>, // Only need to keep a list of disks and their data
|
pub list_of_disks: Vec<disks::DiskData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DataState {
|
pub struct DataState {
|
||||||
@ -45,9 +45,6 @@ pub struct DataState {
|
|||||||
prev_pid_stats: HashMap<String, (f64, Instant)>,
|
prev_pid_stats: HashMap<String, (f64, Instant)>,
|
||||||
prev_idle: f64,
|
prev_idle: f64,
|
||||||
prev_non_idle: f64,
|
prev_non_idle: f64,
|
||||||
prev_net_rx_bytes: u64,
|
|
||||||
prev_net_tx_bytes: u64,
|
|
||||||
prev_net_access_time: Instant,
|
|
||||||
temperature_type: temperature::TemperatureType,
|
temperature_type: temperature::TemperatureType,
|
||||||
last_clean: Instant, // Last time stale data was cleared
|
last_clean: Instant, // Last time stale data was cleared
|
||||||
use_current_cpu_total: bool,
|
use_current_cpu_total: bool,
|
||||||
@ -63,9 +60,6 @@ impl Default for DataState {
|
|||||||
prev_pid_stats: HashMap::new(),
|
prev_pid_stats: HashMap::new(),
|
||||||
prev_idle: 0_f64,
|
prev_idle: 0_f64,
|
||||||
prev_non_idle: 0_f64,
|
prev_non_idle: 0_f64,
|
||||||
prev_net_rx_bytes: 0,
|
|
||||||
prev_net_tx_bytes: 0,
|
|
||||||
prev_net_access_time: Instant::now(),
|
|
||||||
temperature_type: temperature::TemperatureType::Celsius,
|
temperature_type: temperature::TemperatureType::Celsius,
|
||||||
last_clean: Instant::now(),
|
last_clean: Instant::now(),
|
||||||
use_current_cpu_total: false,
|
use_current_cpu_total: false,
|
||||||
@ -97,18 +91,61 @@ impl DataState {
|
|||||||
|
|
||||||
let current_instant = std::time::Instant::now();
|
let current_instant = std::time::Instant::now();
|
||||||
|
|
||||||
// What we want to do: For timed data, if there is an error, just do not add. For other data, just don't update!
|
// Network
|
||||||
push_if_valid(
|
let new_network_data = network::get_network_data(
|
||||||
&network::get_network_data(
|
|
||||||
&self.sys,
|
&self.sys,
|
||||||
&mut self.prev_net_rx_bytes,
|
&self.data.network.last_collection_time,
|
||||||
&mut self.prev_net_tx_bytes,
|
&mut self.data.network.total_rx,
|
||||||
&mut self.prev_net_access_time,
|
&mut self.data.network.total_tx,
|
||||||
¤t_instant,
|
¤t_instant,
|
||||||
)
|
)
|
||||||
.await,
|
.await;
|
||||||
&mut self.data.network,
|
|
||||||
);
|
let joining_points: Option<Vec<network::NetworkJoinPoint>> =
|
||||||
|
if !self.data.network.data_points.is_empty() {
|
||||||
|
if let Some(prev_data) = self
|
||||||
|
.data
|
||||||
|
.network
|
||||||
|
.data_points
|
||||||
|
.get(&self.data.network.last_collection_time)
|
||||||
|
{
|
||||||
|
// If not empty, inject joining points
|
||||||
|
|
||||||
|
let rx_diff = new_network_data.rx as f64 - prev_data.0.rx as f64;
|
||||||
|
let tx_diff = new_network_data.tx as f64 - prev_data.0.tx as f64;
|
||||||
|
let time_gap = current_instant
|
||||||
|
.duration_since(self.data.network.last_collection_time)
|
||||||
|
.as_millis() as f64;
|
||||||
|
|
||||||
|
let mut new_joining_points = Vec::new();
|
||||||
|
|
||||||
|
for idx in 0..100 {
|
||||||
|
new_joining_points.push(network::NetworkJoinPoint {
|
||||||
|
rx: prev_data.0.rx as f64 + rx_diff / 100.0 * idx as f64,
|
||||||
|
tx: prev_data.0.tx as f64 + tx_diff / 100.0 * idx as f64,
|
||||||
|
time_offset_milliseconds: time_gap / 100.0 * (100 - idx) as f64,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Some(new_joining_points)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set values
|
||||||
|
self.data.network.rx = new_network_data.rx;
|
||||||
|
self.data.network.tx = new_network_data.tx;
|
||||||
|
self.data.network.last_collection_time = current_instant;
|
||||||
|
|
||||||
|
// Add new point
|
||||||
|
self.data
|
||||||
|
.network
|
||||||
|
.data_points
|
||||||
|
.insert(current_instant, (new_network_data, joining_points));
|
||||||
|
|
||||||
|
// What we want to do: For timed data, if there is an error, just do not add. For other data, just don't update!
|
||||||
push_if_valid(
|
push_if_valid(
|
||||||
&cpu::get_cpu_data_list(&self.sys, ¤t_instant),
|
&cpu::get_cpu_data_list(&self.sys, ¤t_instant),
|
||||||
&mut self.data.list_of_cpu_packages,
|
&mut self.data.list_of_cpu_packages,
|
||||||
@ -167,6 +204,8 @@ impl DataState {
|
|||||||
self.prev_pid_stats.remove(&stale);
|
self.prev_pid_stats.remove(&stale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: [OPT] cleaning stale network
|
||||||
|
|
||||||
self.data.list_of_cpu_packages = self
|
self.data.list_of_cpu_packages = self
|
||||||
.data
|
.data
|
||||||
.list_of_cpu_packages
|
.list_of_cpu_packages
|
||||||
@ -197,16 +236,6 @@ impl DataState {
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
self.data.network = self
|
|
||||||
.data
|
|
||||||
.network
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.filter(|entry| {
|
|
||||||
clean_instant.duration_since(entry.instant).as_secs() <= self.stale_max_seconds
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
self.data.list_of_io = self
|
self.data.list_of_io = self
|
||||||
.data
|
.data
|
||||||
.list_of_io
|
.list_of_io
|
||||||
|
@ -1,34 +1,58 @@
|
|||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use heim::net;
|
use heim::net;
|
||||||
use heim::units::information::byte;
|
use heim::units::information::byte;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use sysinfo::{NetworkExt, System, SystemExt};
|
use sysinfo::{NetworkExt, System, SystemExt};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone, Debug)]
|
||||||
/// Note all values are in bytes...
|
pub struct NetworkJoinPoint {
|
||||||
pub struct NetworkData {
|
pub rx: f64,
|
||||||
|
pub tx: f64,
|
||||||
|
pub time_offset_milliseconds: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct NetworkStorage {
|
||||||
|
pub data_points: BTreeMap<Instant, (NetworkData, Option<Vec<NetworkJoinPoint>>)>,
|
||||||
pub rx: u64,
|
pub rx: u64,
|
||||||
pub tx: u64,
|
pub tx: u64,
|
||||||
pub total_rx: u64,
|
pub total_rx: u64,
|
||||||
pub total_tx: u64,
|
pub total_tx: u64,
|
||||||
pub instant: Instant,
|
pub last_collection_time: Instant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for NetworkStorage {
|
||||||
|
fn default() -> Self {
|
||||||
|
NetworkStorage {
|
||||||
|
data_points: BTreeMap::default(),
|
||||||
|
rx: 0,
|
||||||
|
tx: 0,
|
||||||
|
total_rx: 0,
|
||||||
|
total_tx: 0,
|
||||||
|
last_collection_time: Instant::now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
/// Note all values are in bytes...
|
||||||
|
pub struct NetworkData {
|
||||||
|
pub rx: u64,
|
||||||
|
pub tx: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_network_data(
|
pub async fn get_network_data(
|
||||||
sys: &System, prev_net_rx_bytes: &mut u64, prev_net_tx_bytes: &mut u64,
|
sys: &System, prev_net_access_time: &Instant, prev_net_rx: &mut u64, prev_net_tx: &mut u64,
|
||||||
prev_net_access_time: &mut Instant, curr_time: &Instant,
|
curr_time: &Instant,
|
||||||
) -> crate::utils::error::Result<NetworkData> {
|
) -> NetworkData {
|
||||||
|
// FIXME: [WIN] Track current total bytes... also is this accurate?
|
||||||
if cfg!(target_os = "windows") {
|
if cfg!(target_os = "windows") {
|
||||||
let network_data = sys.get_network();
|
let network_data = sys.get_network();
|
||||||
|
NetworkData {
|
||||||
*prev_net_access_time = *curr_time;
|
|
||||||
Ok(NetworkData {
|
|
||||||
rx: network_data.get_income(),
|
rx: network_data.get_income(),
|
||||||
tx: network_data.get_outcome(),
|
tx: network_data.get_outcome(),
|
||||||
total_rx: 0,
|
}
|
||||||
total_tx: 0,
|
|
||||||
instant: *prev_net_access_time,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
let mut io_data = net::io_counters();
|
let mut io_data = net::io_counters();
|
||||||
let mut net_rx: u64 = 0;
|
let mut net_rx: u64 = 0;
|
||||||
@ -40,21 +64,23 @@ pub async fn get_network_data(
|
|||||||
net_tx += io.bytes_sent().get::<byte>();
|
net_tx += io.bytes_sent().get::<byte>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let cur_time = Instant::now();
|
let elapsed_time = curr_time
|
||||||
let elapsed_time = cur_time.duration_since(*prev_net_access_time).as_secs_f64();
|
.duration_since(*prev_net_access_time)
|
||||||
|
.as_secs_f64();
|
||||||
|
|
||||||
let rx = ((net_rx - *prev_net_rx_bytes) as f64 / elapsed_time) as u64;
|
if *prev_net_rx == 0 {
|
||||||
let tx = ((net_tx - *prev_net_tx_bytes) as f64 / elapsed_time) as u64;
|
*prev_net_rx = net_rx;
|
||||||
|
}
|
||||||
|
|
||||||
*prev_net_rx_bytes = net_rx;
|
if *prev_net_tx == 0 {
|
||||||
*prev_net_tx_bytes = net_tx;
|
*prev_net_tx = net_tx;
|
||||||
*prev_net_access_time = cur_time;
|
}
|
||||||
Ok(NetworkData {
|
|
||||||
rx,
|
let rx = ((net_rx - *prev_net_rx) as f64 / elapsed_time) as u64;
|
||||||
tx,
|
let tx = ((net_tx - *prev_net_tx) as f64 / elapsed_time) as u64;
|
||||||
total_rx: *prev_net_rx_bytes,
|
|
||||||
total_tx: *prev_net_tx_bytes,
|
*prev_net_rx = net_rx;
|
||||||
instant: *prev_net_access_time,
|
*prev_net_tx = net_tx;
|
||||||
})
|
NetworkData { rx, tx }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,64 +399,60 @@ pub fn update_network_data_points(app_data: &data_collection::Data) -> Converted
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_network_data_points(
|
pub fn convert_network_data_points(
|
||||||
network_data: &[data_collection::network::NetworkData],
|
network_data: &data_collection::network::NetworkStorage,
|
||||||
) -> ConvertedNetworkData {
|
) -> ConvertedNetworkData {
|
||||||
let mut rx: Vec<(f64, f64)> = Vec::new();
|
let mut rx: Vec<(f64, f64)> = Vec::new();
|
||||||
let mut tx: Vec<(f64, f64)> = Vec::new();
|
let mut tx: Vec<(f64, f64)> = Vec::new();
|
||||||
|
|
||||||
for data in network_data {
|
let current_time = network_data.last_collection_time;
|
||||||
let current_time = std::time::Instant::now();
|
for (time, data) in &network_data.data_points {
|
||||||
let rx_data = (
|
let time_from_start: f64 = ((TIME_STARTS_FROM as f64
|
||||||
((TIME_STARTS_FROM as f64
|
- current_time.duration_since(*time).as_millis() as f64)
|
||||||
- current_time.duration_since(data.instant).as_millis() as f64)
|
|
||||||
* 10_f64)
|
* 10_f64)
|
||||||
.floor(),
|
.floor();
|
||||||
if data.rx > 0 {
|
|
||||||
(data.rx as f64).log(2.0)
|
// Insert in joiner points
|
||||||
|
if let Some(joiners) = &data.1 {
|
||||||
|
for joiner in joiners {
|
||||||
|
let offset_time = time_from_start - joiner.time_offset_milliseconds as f64 * 10_f64;
|
||||||
|
rx.push((
|
||||||
|
offset_time,
|
||||||
|
if joiner.rx > 0.0 {
|
||||||
|
(joiner.rx).log(2.0)
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
|
tx.push((
|
||||||
|
offset_time,
|
||||||
|
if joiner.tx > 0.0 {
|
||||||
|
(joiner.tx).log(2.0)
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert in main points
|
||||||
|
let rx_data = (
|
||||||
|
time_from_start,
|
||||||
|
if data.0.rx > 0 {
|
||||||
|
(data.0.rx as f64).log(2.0)
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let tx_data = (
|
let tx_data = (
|
||||||
((TIME_STARTS_FROM as f64
|
time_from_start,
|
||||||
- current_time.duration_since(data.instant).as_millis() as f64)
|
if data.0.tx > 0 {
|
||||||
* 10_f64)
|
(data.0.tx as f64).log(2.0)
|
||||||
.floor(),
|
|
||||||
if data.tx > 0 {
|
|
||||||
(data.tx as f64).log(2.0)
|
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
//debug!("Plotting: {:?} bytes rx, {:?} bytes tx", rx_data, tx_data);
|
|
||||||
|
|
||||||
// Now, inject our joining points...
|
|
||||||
if !rx.is_empty() {
|
|
||||||
let previous_element_data = *(rx.last().unwrap());
|
|
||||||
for idx in 0..50 {
|
|
||||||
rx.push((
|
|
||||||
previous_element_data.0
|
|
||||||
+ ((rx_data.0 - previous_element_data.0) / 50.0 * f64::from(idx)),
|
|
||||||
previous_element_data.1
|
|
||||||
+ ((rx_data.1 - previous_element_data.1) / 50.0 * f64::from(idx)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now, inject our joining points...
|
|
||||||
if !tx.is_empty() {
|
|
||||||
let previous_element_data = *(tx.last().unwrap());
|
|
||||||
for idx in 0..50 {
|
|
||||||
tx.push((
|
|
||||||
previous_element_data.0
|
|
||||||
+ ((tx_data.0 - previous_element_data.0) / 50.0 * f64::from(idx)),
|
|
||||||
previous_element_data.1
|
|
||||||
+ ((tx_data.1 - previous_element_data.1) / 50.0 * f64::from(idx)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rx.push(rx_data);
|
rx.push(rx_data);
|
||||||
tx.push(tx_data);
|
tx.push(tx_data);
|
||||||
}
|
}
|
||||||
@ -466,13 +462,8 @@ pub fn convert_network_data_points(
|
|||||||
let total_tx_converted_result: (f64, String);
|
let total_tx_converted_result: (f64, String);
|
||||||
let tx_converted_result: (f64, String);
|
let tx_converted_result: (f64, String);
|
||||||
|
|
||||||
if let Some(last_num_bytes_entry) = network_data.last() {
|
rx_converted_result = get_exact_byte_values(network_data.rx, false);
|
||||||
rx_converted_result = get_exact_byte_values(last_num_bytes_entry.rx, false);
|
total_rx_converted_result = get_exact_byte_values(network_data.total_rx, false);
|
||||||
total_rx_converted_result = get_exact_byte_values(last_num_bytes_entry.total_rx, false)
|
|
||||||
} else {
|
|
||||||
rx_converted_result = get_exact_byte_values(0, false);
|
|
||||||
total_rx_converted_result = get_exact_byte_values(0, false);
|
|
||||||
}
|
|
||||||
let rx_display = format!("{:.*}{}", 1, rx_converted_result.0, rx_converted_result.1);
|
let rx_display = format!("{:.*}{}", 1, rx_converted_result.0, rx_converted_result.1);
|
||||||
let total_rx_display = if cfg!(not(target_os = "windows")) {
|
let total_rx_display = if cfg!(not(target_os = "windows")) {
|
||||||
format!(
|
format!(
|
||||||
@ -483,13 +474,8 @@ pub fn convert_network_data_points(
|
|||||||
"N/A".to_string()
|
"N/A".to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(last_num_bytes_entry) = network_data.last() {
|
tx_converted_result = get_exact_byte_values(network_data.tx, false);
|
||||||
tx_converted_result = get_exact_byte_values(last_num_bytes_entry.tx, false);
|
total_tx_converted_result = get_exact_byte_values(network_data.total_tx, false);
|
||||||
total_tx_converted_result = get_exact_byte_values(last_num_bytes_entry.total_tx, false);
|
|
||||||
} else {
|
|
||||||
tx_converted_result = get_exact_byte_values(0, false);
|
|
||||||
total_tx_converted_result = get_exact_byte_values(0, false);
|
|
||||||
}
|
|
||||||
let tx_display = format!("{:.*}{}", 1, tx_converted_result.0, tx_converted_result.1);
|
let tx_display = format!("{:.*}{}", 1, tx_converted_result.0, tx_converted_result.1);
|
||||||
let total_tx_display = if cfg!(not(target_os = "windows")) {
|
let total_tx_display = if cfg!(not(target_os = "windows")) {
|
||||||
format!(
|
format!(
|
||||||
|
@ -199,7 +199,7 @@ fn main() -> error::Result<()> {
|
|||||||
}
|
}
|
||||||
futures::executor::block_on(data_state.update_data());
|
futures::executor::block_on(data_state.update_data());
|
||||||
tx.send(Event::Update(Box::from(data_state.data.clone())))
|
tx.send(Event::Update(Box::from(data_state.data.clone())))
|
||||||
.unwrap();
|
.unwrap(); // TODO: [UNWRAP] Might be required, it's in a closure and idk how to deal with it
|
||||||
|
|
||||||
if first_run {
|
if first_run {
|
||||||
// Fix for if you set a really long time for update periods (and just gives a faster first value)
|
// Fix for if you set a really long time for update periods (and just gives a faster first value)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user