From 7efe19da28d1a92aff6b8555ac30722561a6ba22 Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Fri, 3 May 2024 09:53:06 -0700 Subject: [PATCH] perf: speed up SetColors by ~15-25% (#879) The SetColors command was executing SetForegroundColor and then SetBackgroundColor, which writes 2 extra characters per cell compared to writing both colors in one command. This resulted in about 15-25% more FPS (19->24 fps) on a fullscreen (171x51) app that writes every cell with a different foreground and background color, compared to separately using the SetForegroundColor and SetBackgroundColor commands (iTerm2, M2 Macbook Pro). The app is the colors_rgb example in Ratatui, which writes every cell with a different foreground and background color in a loop. The CrosstermBackend was changed to use SetColors instead of SetForegroundColor and SetBackgroundColor. --- src/style.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/style.rs b/src/style.rs index 72c22811..a2618365 100644 --- a/src/style.rs +++ b/src/style.rs @@ -279,13 +279,24 @@ pub struct SetColors(pub Colors); impl Command for SetColors { fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { - if let Some(color) = self.0.foreground { - SetForegroundColor(color).write_ansi(f)?; - } - if let Some(color) = self.0.background { - SetBackgroundColor(color).write_ansi(f)?; + // Writing both foreground and background colors in one command resulted in about 20% more + // FPS (20 to 24 fps) on a fullscreen (171x51) app that writes every cell with a different + // foreground and background color, compared to separately using the SetForegroundColor and + // SetBackgroundColor commands (iTerm2, M2 Macbook Pro). `Esc[38;5;mEsc[48;5;m` (16 + // chars) vs `Esc[38;5;;48;5;m` (14 chars) + match (self.0.foreground, self.0.background) { + (Some(fg), Some(bg)) => { + write!( + f, + csi!("{};{}m"), + Colored::ForegroundColor(fg), + Colored::BackgroundColor(bg) + ) + } + (Some(fg), None) => write!(f, csi!("{}m"), Colored::ForegroundColor(fg)), + (None, Some(bg)) => write!(f, csi!("{}m"), Colored::BackgroundColor(bg)), + (None, None) => Ok(()), } - Ok(()) } #[cfg(windows)]