From ab049e8055466a526956d4ee9bd9a264ab7cad24 Mon Sep 17 00:00:00 2001 From: Daniel Hodges Date: Tue, 21 Jan 2025 13:08:45 -0800 Subject: [PATCH] scxtop: Fill render area by setting max events Scale the max number of events by setting the max number of events based on the rendered area. This ensures that events fill the window space when rendering. Signed-off-by: Daniel Hodges --- tools/scxtop/src/app.rs | 70 +++++++++++++++++++++++++++++++++- tools/scxtop/src/event_data.rs | 8 ++++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/tools/scxtop/src/app.rs b/tools/scxtop/src/app.rs index c064d47f9..893f7a2da 100644 --- a/tools/scxtop/src/app.rs +++ b/tools/scxtop/src/app.rs @@ -52,6 +52,7 @@ pub struct App<'a> { keymap: KeyMap, scheduler: String, max_cpu_events: usize, + max_sched_events: usize, state: AppState, prev_state: AppState, theme: AppTheme, @@ -62,6 +63,7 @@ pub struct App<'a> { pub action_tx: UnboundedSender, pub skel: BpfSkel<'a>, topo: Topology, + large_core_count: bool, collect_cpu_freq: bool, collect_uncore_freq: bool, event_scroll_state: ScrollbarState, @@ -139,6 +141,7 @@ impl<'a> App<'a> { let app = Self { scheduler, max_cpu_events, + max_sched_events: max_cpu_events, keymap, theme: AppTheme::Default, state: AppState::Default, @@ -149,6 +152,7 @@ impl<'a> App<'a> { should_quit: Arc::new(AtomicBool::new(false)), action_tx, skel, + large_core_count: topo.all_cpus.len() >= 128, topo, collect_cpu_freq: true, collect_uncore_freq: true, @@ -308,6 +312,42 @@ impl<'a> App<'a> { Ok(()) } + /// resizes existing sched event data based on new max value. + fn resize_sched_events(&mut self, max_events: usize) { + for events in self.dsq_data.values_mut() { + events.set_max_size(max_events); + } + } + + /// resizes existing events based on new max value. + fn resize_events(&mut self, max_events: usize) { + for node in self.topo.nodes.keys() { + let node_data = self + .node_data + .entry(*node) + .or_insert(NodeData::new(*node, self.max_cpu_events)); + node_data.data.set_max_size(max_events); + } + for llc in self.topo.all_llcs.keys() { + let llc_data = + self.llc_data + .entry(*llc) + .or_insert(LlcData::new(*llc, 0, self.max_cpu_events)); + llc_data.data.set_max_size(max_events); + } + for cpu in self.active_perf_events.keys() { + let cpu_data = self.cpu_data.entry(*cpu).or_insert(CpuData::new( + *cpu, + 0, + 0, + 0, + self.max_cpu_events, + )); + cpu_data.data.set_max_size(max_events); + } + self.max_cpu_events = max_events; + } + /// Runs callbacks to update application state on tick. fn on_tick(&mut self) -> Result<()> { // Add entry for nodes @@ -531,7 +571,12 @@ impl<'a> App<'a> { /// Renders the llc application state. fn render_llc(&mut self, frame: &mut Frame) -> Result<()> { - let [left, right] = Layout::horizontal([Constraint::Fill(1); 2]).areas(frame.area()); + let area = frame.area(); + let area_events = (area.width / 2) as usize; + if self.max_cpu_events != area_events { + self.resize_events(area_events); + } + let [left, right] = Layout::horizontal([Constraint::Fill(1); 2]).areas(area); let [top_left, bottom_left] = Layout::vertical([Constraint::Fill(1); 2]).areas(left); let num_llcs = self.topo.all_llcs.len(); @@ -626,7 +671,12 @@ impl<'a> App<'a> { /// Renders the node application state. fn render_node(&mut self, frame: &mut Frame) -> Result<()> { - let [left, right] = Layout::horizontal([Constraint::Fill(1); 2]).areas(frame.area()); + let area = frame.area(); + let area_events = (area.width / 2) as usize; + if self.max_cpu_events != area_events { + self.resize_events(area_events); + } + let [left, right] = Layout::horizontal([Constraint::Fill(1); 2]).areas(area); let [top_left, bottom_left] = Layout::vertical([Constraint::Fill(1); 2]).areas(left); let num_nodes = self.topo.nodes.len(); @@ -839,6 +889,12 @@ impl<'a> App<'a> { ) -> Result<()> { let num_dsqs = self.dsq_data.len(); let mut dsq_constraints = Vec::new(); + + let area_width = area.width as usize; + if area_width != self.max_sched_events { + self.resize_sched_events(area_width); + } + if num_dsqs == 0 { let block = Block::default() .title_top( @@ -1170,6 +1226,16 @@ impl<'a> App<'a> { vec![Constraint::Ratio(1, num_nodes.try_into().unwrap()); num_nodes]; let node_areas = Layout::vertical(constraints).split(area); + let area = frame.area(); + let area_events = if !self.large_core_count { + (area.width / 4) as usize + } else { + (area.width / 8) as usize + }; + if self.max_cpu_events != area_events { + self.resize_events(area_events); + } + for (i, node) in self.topo.nodes.values().enumerate() { let node_constraints = vec![Constraint::Percentage(2), Constraint::Percentage(98)]; diff --git a/tools/scxtop/src/event_data.rs b/tools/scxtop/src/event_data.rs index 4c66f67f9..71c38b59a 100644 --- a/tools/scxtop/src/event_data.rs +++ b/tools/scxtop/src/event_data.rs @@ -45,6 +45,14 @@ impl EventData { } } + /// Sets the max size and truncates events greater than the max. + pub fn set_max_size(&mut self, max_data_size: usize) { + self.max_data_size = max_data_size; + for event_data in self.data.values_mut() { + event_data.truncate(self.max_data_size); + } + } + /// Clears an event. pub fn clear_event(&mut self, event: String) { self.data.remove(&event);