From 7fceb4878fd3da27cea9562f20342e5fb64c37eb Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Mon, 6 Dec 2021 09:14:15 +0100 Subject: [PATCH] Load themes lazily for improved startup time (#1969) This is for #951. Syntax lazy-loading will come later and have a much bigger impact, but lazy-loading of themes does not have negligible impact. --- CHANGELOG.md | 1 + assets/themes.bin | Bin 21378 -> 40508 bytes src/assets.rs | 32 +++++++---- src/assets/build_assets.rs | 14 +++-- src/assets/lazy_theme_set.rs | 104 +++++++++++++++++++++++++++++++++++ 5 files changed, 134 insertions(+), 17 deletions(-) create mode 100644 src/assets/lazy_theme_set.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 439cb112..c7971bb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - Load cached assets as fast as integrated assets, see #1753 (@Enselic) - Greatly reduce startup time in loop-through mode, e.g. when redirecting output. Instead of *50 ms* - *100 ms*, startup takes *5 ms* - *10 ms*. See #1747 (@Enselic) +- Load themes lazily to make bat start 25% faster when disregarding syntax load time. See #1969 (@Enselic) ## Other diff --git a/assets/themes.bin b/assets/themes.bin index 9c31eb7d6033a1f32640dfbe5060b315f2b95407..5d3091278652d548cf1a56e9c3e5646f59419fac 100644 GIT binary patch literal 40508 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ΝPA{nmQ0M7{y6rs>{*L zYArMA(ZY63dL&{^i^&H^CgYaiMsXr!nKXN=v6zkE#pIlpelBaZdZZUDk=aWcG%FV7k>o%Vv^(~WMHMrh zGnu`xrpjc*#YoBxZC3f{p@`#--PAIEzHZM&)yN8ADALgMj?l>NnQg3ep^Z5uB^CsQ znR4GcP9`p{%c<5k5iYD-DO&}T7F5+@LIAiF9=c)b?asu%qh?VX$vsqdIvW1=m%JaT zS0GjQvsPbnQl_=<>P~E`y&uQ)CoG0P4VX}5ySfy3bgIv6ieV^DQ^qykh3d<$>zl0Y zfKGryRt`s%fRh(2X*ZdW{-)Q&nGULphXU7CBmM zw;c8FtIr3E5IHx%$~zj$M4_dD?_AcW;Tq^hCKc3Xf@byf-Y1T%q(WVJW0Td=M3AIW z0MJ8eLf@AL14ILI}$btb|ydY;=Q>-eEm2fp=VjUOj+ol{MTNc8JEtd?$=#}ZVZ zeo<#)6BJhPr3*Eo7IU|vVv&j$=}q{SK5$UwLoCS)=8P`lgqNL|VoI9RKiW6BGi9sc ze(ZLwYg`f!H8zaYQ-Yw>Ku`{>XFCYIkd_L)qt%bQZrkg?>La&t`{5F^8Sp_y>H-rR zQHyX+;d$GT0h&8E|Eql>_s>4Dux0$e@_0#0DvV45`??BS&BWD>fP0JgD=TN)rNynb z-eLGDuN6{YHn5cl!QEkMJgOq1{Ev+Bu`?zWmHS;;UI3BjTws9vZPmWUW}vPxCPw^H z;Qp?GMqlwK>AeDS{9T2jhAV>3mhz|G=UvawZ^O>3==Yt{dX`M^*VBU&a!FD&eD921 zXxT2@sTWjj*~)lA)3GzN3cUDKkgODmI8VFox0&FV&9OTWAFsw+-Otl(aMC=z&)$di z9k$gP+-<)v?aw1z*mriiC%(6E%(IcZJ9x=c@0W&DUzpq-i{~e{LEo#L8(TjAe6V7Z z7ni5q2Uy-EqbV~5lq}hHJG~zv3!?UUn`8`=xD+2v^03`nt(U|aI=DkMlY0(vN)>yr_NhRM=O@N^6+({5K8Jg6j)k zUMUP$RtytS_jmx!muYOIu@C1=YU9Dq52!ig`XjJv;6z(41oZs?2UUda9^%g-XfHox zEh7kE@0}w!w^evfKKLmO;i5et-61)Id|DA&h&IY9VfYj8l2jne-`&ppqeOx%6Y|sQo2dNGuy_gjXmS`dA$k%ao-^`r6$W7psB{H=C)~dSwlXEiOnm=W!-CLG~;r z;6Fg>m1Iy!ZlD+E+NQs463b2)=AUH(d6q@bW07*m!lnY;Irql?FASsmnMWzz9 zKHptFO4UI=w*PE(HrsAf4P!viZve%bN{BI(ANbqR!eUCtmh-ZpthMpkp6V=)!aYtG zf?kHxZWksK#`wTco7pO_F2K@Hnr1x(O5GB=(YHs=;10avs_1}mI5^CL%?Fb3xbIw1 z$Lvdv7Q5(LSPo8k7l7hnoYmw%obRm>#r;qI(L`8uOEHdGVxUg#n zKN>p=`eG43lHGMKm=sSbhFFz1T{n6pG&Co991(awWPV1ZdLCD=b-9Ie`#CYyiFN*Q~LES<8=jN+VC>Dc9L|m@VMcxum$S?6JKNK=^u5>-Zz#N>a$sCxu<>wt;-t;-Cw}O zecA#%v*s!?f68D#b!5u8w)oM>ETsXxj_}4eGd{L3Q5Sg{i49!i_Z;$S|MK7XE~*Kk z&(BJVWZUuQzVkS=Y-p_G_m2v)%=Y06jSz1b8gvtzt7?4_%=;JeF$(O-I)Fa0E2mPL zwuw}6^0tO?g-&+hQ}OPy?k_D>+2Id;gaz$y08dvNuhj*R3HAv>L&3@-NV|D_Bf!#a zeh!0iJtfotYp^c-oL>%nTQ$PA8N`9DJ+>$?bKu&gI2Ob^iQaC$+dU?0UrmP)LDiYiHubQI0R@dV&69l#viS;3|e#e>(qcK8ET=C1~Q-u!wh2 z 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 literal 21378 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 Vl8CSvOa1`$y+z)g{|^SVFGk@1N9h0n diff --git a/src/assets.rs b/src/assets.rs index 206664cc..9e734023 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -4,7 +4,7 @@ use std::path::Path; use once_cell::unsync::OnceCell; -use syntect::highlighting::{Theme, ThemeSet}; +use syntect::highlighting::Theme; use syntect::parsing::{SyntaxReference, SyntaxSet}; use path_abs::PathAbs; @@ -15,6 +15,8 @@ use crate::syntax_mapping::ignored_suffixes::IgnoredSuffixes; use crate::syntax_mapping::MappingTarget; use crate::{bat_warning, SyntaxMapping}; +use lazy_theme_set::LazyThemeSet; + use serialized_syntax_set::*; #[cfg(feature = "build-assets")] @@ -23,6 +25,7 @@ pub use crate::assets::build_assets::*; pub(crate) mod assets_metadata; #[cfg(feature = "build-assets")] mod build_assets; +mod lazy_theme_set; mod serialized_syntax_set; #[derive(Debug)] @@ -30,7 +33,7 @@ pub struct HighlightingAssets { syntax_set_cell: OnceCell, serialized_syntax_set: SerializedSyntaxSet, - theme_set: ThemeSet, + theme_set: LazyThemeSet, fallback_theme: Option<&'static str>, } @@ -43,11 +46,17 @@ pub struct SyntaxReferenceInSet<'a> { /// Compress for size of ~700 kB instead of ~4600 kB at the cost of ~30% longer deserialization time pub(crate) const COMPRESS_SYNTAXES: bool = true; -/// Compress for size of ~20 kB instead of ~200 kB at the cost of ~30% longer deserialization time -pub(crate) const COMPRESS_THEMES: bool = true; +/// We don't want to compress our [LazyThemeSet] since the lazy-loaded themes +/// within it are already compressed, and compressing another time just makes +/// performance suffer +pub(crate) const COMPRESS_THEMES: bool = false; + +/// Compress for size of ~40 kB instead of ~200 kB without much difference in +/// performance due to lazy-loading +pub(crate) const COMPRESS_LAZY_THEMES: bool = true; impl HighlightingAssets { - fn new(serialized_syntax_set: SerializedSyntaxSet, theme_set: ThemeSet) -> Self { + fn new(serialized_syntax_set: SerializedSyntaxSet, theme_set: LazyThemeSet) -> Self { HighlightingAssets { syntax_set_cell: OnceCell::new(), serialized_syntax_set, @@ -95,12 +104,12 @@ impl HighlightingAssets { Ok(self.get_syntax_set()?.syntaxes()) } - fn get_theme_set(&self) -> &ThemeSet { + fn get_theme_set(&self) -> &LazyThemeSet { &self.theme_set } pub fn themes(&self) -> impl Iterator { - self.get_theme_set().themes.keys().map(|s| s.as_ref()) + self.get_theme_set().themes() } /// Use [Self::get_syntax_for_path] instead @@ -175,7 +184,7 @@ impl HighlightingAssets { } pub(crate) fn get_theme(&self, theme: &str) -> &Theme { - match self.get_theme_set().themes.get(theme) { + match self.get_theme_set().get(theme) { Some(theme) => theme, None => { if theme == "ansi-light" || theme == "ansi-dark" { @@ -185,8 +194,9 @@ impl HighlightingAssets { if !theme.is_empty() { bat_warning!("Unknown theme '{}', using default.", theme) } - &self.get_theme_set().themes - [self.fallback_theme.unwrap_or_else(|| Self::default_theme())] + self.get_theme_set() + .get(self.fallback_theme.unwrap_or_else(|| Self::default_theme())) + .expect("something is very wrong if the default theme is missing") } } } @@ -291,7 +301,7 @@ pub(crate) fn get_serialized_integrated_syntaxset() -> &'static [u8] { include_bytes!("../assets/syntaxes.bin") } -pub(crate) fn get_integrated_themeset() -> ThemeSet { +pub(crate) fn get_integrated_themeset() -> LazyThemeSet { from_binary(include_bytes!("../assets/themes.bin"), COMPRESS_THEMES) } diff --git a/src/assets/build_assets.rs b/src/assets/build_assets.rs index 34fa150b..fe78f2b1 100644 --- a/src/assets/build_assets.rs +++ b/src/assets/build_assets.rs @@ -1,4 +1,6 @@ +use std::convert::TryInto; use std::path::Path; + use syntect::highlighting::ThemeSet; use syntect::parsing::{SyntaxSet, SyntaxSetBuilder}; @@ -10,7 +12,7 @@ pub fn build( target_dir: &Path, current_version: &str, ) -> Result<()> { - let theme_set = build_theme_set(source_dir, include_integrated_assets); + let theme_set = build_theme_set(source_dir, include_integrated_assets)?; let syntax_set_builder = build_syntax_set_builder(source_dir, include_integrated_assets)?; @@ -21,9 +23,9 @@ pub fn build( write_assets(&theme_set, &syntax_set, target_dir, current_version) } -fn build_theme_set(source_dir: &Path, include_integrated_assets: bool) -> ThemeSet { +fn build_theme_set(source_dir: &Path, include_integrated_assets: bool) -> Result { let mut theme_set = if include_integrated_assets { - crate::assets::get_integrated_themeset() + crate::assets::get_integrated_themeset().try_into()? } else { ThemeSet::new() }; @@ -45,7 +47,7 @@ fn build_theme_set(source_dir: &Path, include_integrated_assets: bool) -> ThemeS ); } - theme_set + theme_set.try_into() } fn build_syntax_set_builder( @@ -85,7 +87,7 @@ fn print_unlinked_contexts(syntax_set: &SyntaxSet) { } fn write_assets( - theme_set: &ThemeSet, + theme_set: &LazyThemeSet, syntax_set: &SyntaxSet, target_dir: &Path, current_version: &str, @@ -114,7 +116,7 @@ fn write_assets( Ok(()) } -fn asset_to_contents( +pub(crate) fn asset_to_contents( asset: &T, description: &str, compressed: bool, diff --git a/src/assets/lazy_theme_set.rs b/src/assets/lazy_theme_set.rs new file mode 100644 index 00000000..bf749154 --- /dev/null +++ b/src/assets/lazy_theme_set.rs @@ -0,0 +1,104 @@ +use super::*; + +use std::collections::BTreeMap; +use std::convert::TryFrom; + +use serde::Deserialize; +use serde::Serialize; + +use once_cell::unsync::OnceCell; + +use syntect::highlighting::{Theme, ThemeSet}; + +/// Same structure as a [`syntect::highlighting::ThemeSet`] but with themes +/// stored in raw serialized form, and deserialized on demand. +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct LazyThemeSet { + /// This is a [`BTreeMap`] because that's what [`syntect::highlighting::ThemeSet`] uses + themes: BTreeMap, +} + +/// Stores raw serialized data for a theme with methods to lazily deserialize +/// (load) the theme. +#[derive(Debug, Serialize, Deserialize)] +struct LazyTheme { + serialized: Vec, + + #[serde(skip, default = "OnceCell::new")] + deserialized: OnceCell, +} + +impl LazyThemeSet { + /// Lazily load the given theme + pub fn get(&self, name: &str) -> Option<&Theme> { + self.themes.get(name).and_then(|lazy_theme| { + lazy_theme + .deserialized + .get_or_try_init(|| lazy_theme.deserialize()) + .ok() + }) + } + + /// Returns the name of all themes. + pub fn themes(&self) -> impl Iterator { + self.themes.keys().map(|name| name.as_ref()) + } +} + +impl LazyTheme { + fn deserialize(&self) -> Result { + asset_from_contents( + &self.serialized[..], + "lazy-loaded theme", + COMPRESS_LAZY_THEMES, + ) + } +} + +impl TryFrom for ThemeSet { + type Error = Error; + + /// Since the user might want to add custom themes to bat, we need a way to + /// convert from a `LazyThemeSet` to a regular [`ThemeSet`] so that more + /// themes can be added. This function does that pretty straight-forward + /// conversion. + fn try_from(lazy_theme_set: LazyThemeSet) -> Result { + let mut theme_set = ThemeSet::default(); + + for (name, lazy_theme) in lazy_theme_set.themes { + theme_set.themes.insert(name, lazy_theme.deserialize()?); + } + + Ok(theme_set) + } +} + +#[cfg(feature = "build-assets")] +impl TryFrom for LazyThemeSet { + type Error = Error; + + /// To collect themes, a [`ThemeSet`] is needed. Once all desired themes + /// have been added, we need a way to convert that into [`LazyThemeSet`] so + /// that themes can be lazy-loaded later. This function does that + /// conversion. + fn try_from(theme_set: ThemeSet) -> Result { + let mut lazy_theme_set = LazyThemeSet::default(); + + for (name, theme) in theme_set.themes { + // All we have to do is to serialize the theme + let lazy_theme = LazyTheme { + serialized: crate::assets::build_assets::asset_to_contents( + &theme, + &format!("theme {}", name), + COMPRESS_LAZY_THEMES, + )?, + deserialized: OnceCell::new(), + }; + + // Ok done, now we can add it + lazy_theme_set.themes.insert(name, lazy_theme); + } + + Ok(lazy_theme_set) + } +}