mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-09-25 18:49:06 +02:00
bug/refactor: draw average CPU last, refactor CPU data code (#1804)
This PR makes it so we draw the average CPU on top again. This also refactors internals to have the average CPU stored separately.
This commit is contained in:
parent
58a9a643a4
commit
43e1b34899
@ -29,6 +29,7 @@ That said, these are more guidelines rather than hardset rules, though the proje
|
||||
### Bug Fixes
|
||||
|
||||
- [#1800](https://github.com/ClementTsang/bottom/pull/1800): Fix colon at end of process name in Linux.
|
||||
- [#1804](https://github.com/ClementTsang/bottom/pull/1804): Draw average CPU last again.
|
||||
|
||||
## [0.11.1] - 2025-08-15
|
||||
|
||||
|
@ -30,7 +30,7 @@ pub struct StoredData {
|
||||
pub arc_harvest: Option<MemData>,
|
||||
#[cfg(feature = "gpu")]
|
||||
pub gpu_harvest: Vec<(String, MemData)>,
|
||||
pub cpu_harvest: cpu::CpuHarvest,
|
||||
pub cpu_harvest: Vec<cpu::CpuData>,
|
||||
pub load_avg_harvest: cpu::LoadAvgHarvest,
|
||||
pub process_data: ProcessData,
|
||||
/// TODO: (points_rework_v1) Might be a better way to do this without having to store here?
|
||||
@ -51,7 +51,7 @@ impl Default for StoredData {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
cache_harvest: None,
|
||||
swap_harvest: None,
|
||||
cpu_harvest: cpu::CpuHarvest::default(),
|
||||
cpu_harvest: Default::default(),
|
||||
load_avg_harvest: cpu::LoadAvgHarvest::default(),
|
||||
process_data: Default::default(),
|
||||
prev_io: Vec::default(),
|
||||
@ -114,7 +114,25 @@ impl StoredData {
|
||||
}
|
||||
|
||||
if let Some(cpu) = data.cpu {
|
||||
self.cpu_harvest = cpu;
|
||||
self.cpu_harvest.clear();
|
||||
|
||||
if let Some(avg) = cpu.avg {
|
||||
self.cpu_harvest.push(cpu::CpuData {
|
||||
data_type: cpu::CpuDataType::Avg,
|
||||
usage: avg,
|
||||
});
|
||||
}
|
||||
|
||||
self.cpu_harvest
|
||||
.extend(
|
||||
cpu.cpus
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(core, usage)| cpu::CpuData {
|
||||
data_type: cpu::CpuDataType::Cpu(core as u32),
|
||||
usage,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(load_avg) = data.load_avg {
|
||||
|
@ -38,6 +38,9 @@ pub struct TimeSeriesData {
|
||||
/// CPU data.
|
||||
pub cpu: Vec<Values>,
|
||||
|
||||
/// Average CPU data.
|
||||
pub avg_cpu: Values,
|
||||
|
||||
/// RAM memory data.
|
||||
pub ram: Values,
|
||||
|
||||
@ -70,10 +73,12 @@ impl TimeSeriesData {
|
||||
self.tx.insert_break();
|
||||
}
|
||||
|
||||
if let Some(cpu) = &data.cpu {
|
||||
match self.cpu.len().cmp(&cpu.len()) {
|
||||
if let Some(cpu_harvest) = &data.cpu {
|
||||
let cpus = &cpu_harvest.cpus;
|
||||
|
||||
match self.cpu.len().cmp(&cpus.len()) {
|
||||
Ordering::Less => {
|
||||
let diff = cpu.len() - self.cpu.len();
|
||||
let diff = cpus.len() - self.cpu.len();
|
||||
self.cpu.reserve_exact(diff);
|
||||
|
||||
for _ in 0..diff {
|
||||
@ -81,7 +86,7 @@ impl TimeSeriesData {
|
||||
}
|
||||
}
|
||||
Ordering::Greater => {
|
||||
let diff = self.cpu.len() - cpu.len();
|
||||
let diff = self.cpu.len() - cpus.len();
|
||||
let offset = self.cpu.len() - diff;
|
||||
|
||||
for curr in &mut self.cpu[offset..] {
|
||||
@ -91,13 +96,20 @@ impl TimeSeriesData {
|
||||
Ordering::Equal => {}
|
||||
}
|
||||
|
||||
for (curr, new_data) in self.cpu.iter_mut().zip(cpu.iter()) {
|
||||
curr.push(new_data.usage.into());
|
||||
for (curr, new_data) in self.cpu.iter_mut().zip(cpus.iter()) {
|
||||
curr.push((*new_data).into());
|
||||
}
|
||||
|
||||
// If there isn't avg then we never had any to begin with.
|
||||
if let Some(avg) = cpu_harvest.avg {
|
||||
self.avg_cpu.push(avg.into());
|
||||
}
|
||||
} else {
|
||||
for c in &mut self.cpu {
|
||||
c.insert_break();
|
||||
}
|
||||
|
||||
self.avg_cpu.insert_break();
|
||||
}
|
||||
|
||||
if let Some(memory) = &data.memory {
|
||||
|
@ -149,7 +149,8 @@ impl Painter {
|
||||
CpuDataType::Avg => ("AVG".to_string(), self.styles.avg_cpu_colour),
|
||||
CpuDataType::Cpu(index) => (
|
||||
format!("{index:<3}",),
|
||||
self.styles.cpu_colour_styles[index % self.styles.cpu_colour_styles.len()],
|
||||
self.styles.cpu_colour_styles
|
||||
[(index as usize) % self.styles.cpu_colour_styles.len()],
|
||||
),
|
||||
};
|
||||
|
||||
|
@ -119,7 +119,6 @@ impl Painter {
|
||||
fn generate_points<'a>(
|
||||
&self, cpu_widget_state: &'a CpuWidgetState, data: &'a StoredData, show_avg_cpu: bool,
|
||||
) -> Vec<GraphData<'a>> {
|
||||
let show_avg_offset = if show_avg_cpu { AVG_POSITION } else { 0 };
|
||||
let current_scroll_position = cpu_widget_state.table.state.current_index;
|
||||
let cpu_entries = &data.cpu_harvest;
|
||||
let cpu_points = &data.timeseries_data.cpu;
|
||||
@ -128,39 +127,59 @@ impl Painter {
|
||||
if current_scroll_position == ALL_POSITION {
|
||||
// This case ensures the other cases cannot have the position be equal to 0.
|
||||
|
||||
cpu_points
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(itx, values)| {
|
||||
let style = if show_avg_cpu && itx == AVG_POSITION {
|
||||
self.styles.avg_cpu_colour
|
||||
} else if itx == ALL_POSITION {
|
||||
self.styles.all_cpu_colour
|
||||
} else {
|
||||
self.styles.cpu_colour_styles
|
||||
[(itx - show_avg_offset) % self.styles.cpu_colour_styles.len()]
|
||||
};
|
||||
let capacity = if show_avg_cpu {
|
||||
cpu_points.len() + 1
|
||||
} else {
|
||||
cpu_points.len()
|
||||
};
|
||||
let mut points = Vec::with_capacity(capacity);
|
||||
|
||||
GraphData::default().style(style).time(time).values(values)
|
||||
})
|
||||
.collect()
|
||||
points.extend(cpu_points.iter().enumerate().map(|(itx, values)| {
|
||||
let style_index = itx % self.styles.cpu_colour_styles.len();
|
||||
let style = self.styles.cpu_colour_styles[style_index];
|
||||
|
||||
GraphData::default().style(style).time(time).values(values)
|
||||
}));
|
||||
|
||||
// We draw avg last so it is drawn on top.
|
||||
if show_avg_cpu {
|
||||
points.push(
|
||||
GraphData::default()
|
||||
.style(self.styles.avg_cpu_colour)
|
||||
.time(time)
|
||||
.values(&data.timeseries_data.avg_cpu),
|
||||
);
|
||||
}
|
||||
|
||||
points
|
||||
} else if let Some(CpuData { .. }) = cpu_entries.get(current_scroll_position - 1) {
|
||||
// We generally subtract one from current scroll position because of the all entry.
|
||||
|
||||
let style = if show_avg_cpu && current_scroll_position == AVG_POSITION {
|
||||
let show_avg_offset = if show_avg_cpu { AVG_POSITION } else { 0 };
|
||||
let is_avg = show_avg_cpu && current_scroll_position == AVG_POSITION;
|
||||
|
||||
let style = if is_avg {
|
||||
self.styles.avg_cpu_colour
|
||||
} else {
|
||||
let offset_position = current_scroll_position - 1;
|
||||
self.styles.cpu_colour_styles
|
||||
[(offset_position - show_avg_offset) % self.styles.cpu_colour_styles.len()]
|
||||
self.styles.cpu_colour_styles[(current_scroll_position - 1 - show_avg_offset)
|
||||
% self.styles.cpu_colour_styles.len()]
|
||||
};
|
||||
|
||||
vec![
|
||||
GraphData::default()
|
||||
.style(style)
|
||||
.time(time)
|
||||
.values(&cpu_points[current_scroll_position - 1]),
|
||||
]
|
||||
if is_avg {
|
||||
vec![
|
||||
GraphData::default()
|
||||
.style(style)
|
||||
.time(time)
|
||||
.values(&data.timeseries_data.avg_cpu),
|
||||
]
|
||||
} else {
|
||||
vec![
|
||||
GraphData::default()
|
||||
.style(style)
|
||||
.time(time)
|
||||
.values(&cpu_points[current_scroll_position - 1 - show_avg_offset]),
|
||||
]
|
||||
}
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ pub type LoadAvgHarvest = [f32; 3];
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum CpuDataType {
|
||||
Avg,
|
||||
Cpu(usize),
|
||||
Cpu(u32),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -17,4 +17,8 @@ pub struct CpuData {
|
||||
pub usage: f32,
|
||||
}
|
||||
|
||||
pub type CpuHarvest = Vec<CpuData>;
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct CpuHarvest {
|
||||
pub avg: Option<f32>,
|
||||
pub cpus: Vec<f32>,
|
||||
}
|
||||
|
@ -3,31 +3,19 @@
|
||||
|
||||
use sysinfo::System;
|
||||
|
||||
use super::{CpuData, CpuDataType, CpuHarvest};
|
||||
use super::CpuHarvest;
|
||||
use crate::collection::error::CollectionResult;
|
||||
|
||||
pub fn get_cpu_data_list(sys: &System, show_average_cpu: bool) -> CollectionResult<CpuHarvest> {
|
||||
let mut cpus = vec![];
|
||||
let avg = show_average_cpu.then(|| sys.global_cpu_usage());
|
||||
|
||||
if show_average_cpu {
|
||||
cpus.push(CpuData {
|
||||
data_type: CpuDataType::Avg,
|
||||
usage: sys.global_cpu_usage(),
|
||||
})
|
||||
}
|
||||
let cpus = sys
|
||||
.cpus()
|
||||
.iter()
|
||||
.map(|cpu| cpu.cpu_usage())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
cpus.extend(
|
||||
sys.cpus()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, cpu)| CpuData {
|
||||
data_type: CpuDataType::Cpu(i),
|
||||
usage: cpu.cpu_usage(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
Ok(cpus)
|
||||
Ok(CpuHarvest { avg, cpus })
|
||||
}
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
|
@ -102,6 +102,7 @@ impl DataToCell<CpuWidgetColumn> for CpuWidgetTableData {
|
||||
} => match data_type {
|
||||
CpuDataType::Avg => painter.styles.avg_cpu_colour,
|
||||
CpuDataType::Cpu(index) => {
|
||||
let index = *index as usize;
|
||||
painter.styles.cpu_colour_styles[index % painter.styles.cpu_colour_styles.len()]
|
||||
}
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user