Span optimizations

This commit is contained in:
Marco De Araujo 2026-01-19 13:34:37 -04:00
parent d63c701867
commit 975c4b1eaf

View file

@ -6,11 +6,14 @@ use std::{
sync::{OnceLock, RwLock}, sync::{OnceLock, RwLock},
}; };
use crate::i18n::t; use crate::{
use crate::ui::dashboard::{ i18n::t,
ui::dashboard::{
MonitorStatus, MonitorViewState, MonitorStatus, MonitorViewState,
model::{BORDER_LINES_VIEW, DashboardViewState, GroupViewState}, model::{BORDER_LINES_VIEW, DashboardViewState, GroupViewState},
},
}; };
use once_cell::sync::Lazy;
use ratatui::{ use ratatui::{
Frame, Frame,
layout::{Alignment, Constraint, Direction, Layout, Rect}, layout::{Alignment, Constraint, Direction, Layout, Rect},
@ -21,8 +24,17 @@ use ratatui::{
const STATUS_LINE_LENGTH: usize = 100; const STATUS_LINE_LENGTH: usize = 100;
const MAX_NAME_LENGTH: usize = 30; const MAX_NAME_LENGTH: usize = 30;
static STATUS_SPANS: OnceLock<HashMap<MonitorStatus, Span<'static>>> = OnceLock::new();
static STATUS_LINE_CACHE: OnceLock<RwLock<HashMap<u64, Vec<Span<'static>>>>> = OnceLock::new(); static UP_SPAN: Lazy<Span<'static>> =
Lazy::new(|| Span::styled("", Style::default().fg(Color::Green)));
static DOWN_SPAN: Lazy<Span<'static>> =
Lazy::new(|| Span::styled("", Style::default().fg(Color::Red)));
static UNKNOWN_SPAN: Lazy<Span<'static>> =
Lazy::new(|| Span::styled("", Style::default().fg(Color::Yellow)));
static STATUS_LINE_CACHE: OnceLock<RwLock<HashMap<u64, Vec<&'static Span<'static>>>>> = OnceLock::new();
pub fn render_monitor_list(main_frame: &mut Frame, area: Rect, state: &mut DashboardViewState) { pub fn render_monitor_list(main_frame: &mut Frame, area: Rect, state: &mut DashboardViewState) {
let available_height = area.height as usize; let available_height = area.height as usize;
@ -209,24 +221,12 @@ fn get_formated_line(text: String, color: Color, modifier: Modifier) -> Line<'st
)]) )])
} }
fn get_cached_status_span(status: &MonitorStatus) -> Span<'static> { fn get_status_span(status: &MonitorStatus) -> &'static Span<'static> {
let cache = STATUS_SPANS.get_or_init(|| { match status {
let mut m = HashMap::new(); MonitorStatus::Up => &UP_SPAN,
m.insert( MonitorStatus::Down => &DOWN_SPAN,
MonitorStatus::Up, MonitorStatus::Unknown => &UNKNOWN_SPAN,
Span::styled("", Style::default().fg(Color::Green)), }
);
m.insert(
MonitorStatus::Down,
Span::styled("", Style::default().fg(Color::Red)),
);
m.insert(
MonitorStatus::Unknown,
Span::styled("", Style::default().fg(Color::Yellow)),
);
m
});
cache.get(status).cloned().unwrap_or_default()
} }
fn title_style() -> Style { fn title_style() -> Style {
@ -252,27 +252,25 @@ fn get_cached_status_line(status_history: &[MonitorStatus]) -> Line<'static> {
{ {
let read = cache.read().unwrap(); let read = cache.read().unwrap();
if let Some(spans) = read.get(&hash) { if let Some(spans) = read.get(&hash) {
return Line::from(spans.clone()); return Line::from(spans.iter().map(|&span| span.clone()).collect::<Vec<_>>());
} }
} }
let spans: Vec<Span<'static>> = status_history let spans: Vec<&'static Span<'static>> = status_history
.iter() .iter()
.rev() .rev()
.take(STATUS_LINE_LENGTH) .take(STATUS_LINE_LENGTH)
.map(|status| get_cached_status_span(status)) .map(|status| get_status_span(status))
.collect(); .collect();
let mut write = cache.write().unwrap(); let mut write = cache.write().unwrap();
if write.len() > 1000 { if write.len() > 1000 {
let keys_to_remove: Vec<_> = write.keys().take(250).copied().collect(); let keys_to_remove: Vec<_> = write.keys().take(250).copied().collect();
for key in keys_to_remove { for key in keys_to_remove {
write.remove(&key); write.remove(&key);
} }
} }
write.insert(hash, spans.clone()); write.insert(hash, spans.clone());
Line::from(spans) Line::from(spans.iter().map(|&span| span.clone()).collect::<Vec<_>>())
} }