mirror of
https://github.com/sharkdp/bat.git
synced 2024-11-25 17:23:39 +01:00
Reduce startup time in loop-through mode with 80%-90%
Instead of 100 ms - 50 ms, startup takes 10 ms - 5 ms. HighlightingAssets::get_syntax_set() is never called when e.g. piping the bat output to a file (see Config::loop_through), so by loading the SyntaxSet only when needed, we radically improve startup time when it is not needed.
This commit is contained in:
parent
1bac3750df
commit
6acec2c074
@ -9,6 +9,7 @@
|
||||
## Other
|
||||
|
||||
- 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)
|
||||
|
||||
|
||||
## Syntaxes
|
||||
|
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -101,6 +101,7 @@ dependencies = [
|
||||
"globset",
|
||||
"grep-cli",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"nix",
|
||||
"path_abs",
|
||||
"predicates",
|
||||
|
@ -38,6 +38,7 @@ ansi_term = "^0.12.1"
|
||||
ansi_colours = "^1.0"
|
||||
console = "0.14.1"
|
||||
lazy_static = { version = "1.4", optional = true }
|
||||
lazycell = "1.0"
|
||||
wild = { version = "2.0", optional = true }
|
||||
content_inspector = "0.2.4"
|
||||
encoding = "0.2"
|
||||
|
@ -1,7 +1,9 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use lazycell::LazyCell;
|
||||
|
||||
use syntect::dumps::{dump_to_file, from_binary, from_reader};
|
||||
use syntect::highlighting::{Theme, ThemeSet};
|
||||
@ -17,7 +19,8 @@ use crate::syntax_mapping::{MappingTarget, SyntaxMapping};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HighlightingAssets {
|
||||
syntax_set: SyntaxSet,
|
||||
syntax_set_cell: LazyCell<SyntaxSet>,
|
||||
serialized_syntax_set: Option<SerializedSyntaxSet>,
|
||||
pub(crate) theme_set: ThemeSet,
|
||||
fallback_theme: Option<&'static str>,
|
||||
}
|
||||
@ -40,9 +43,21 @@ const IGNORED_SUFFIXES: [&str; 10] = [
|
||||
];
|
||||
|
||||
impl HighlightingAssets {
|
||||
fn new(syntax_set: SyntaxSet, theme_set: ThemeSet) -> Self {
|
||||
fn new(
|
||||
syntax_set: Option<SyntaxSet>,
|
||||
serialized_syntax_set: Option<SerializedSyntaxSet>,
|
||||
theme_set: ThemeSet,
|
||||
) -> Self {
|
||||
assert!(syntax_set.is_some() || serialized_syntax_set.is_some());
|
||||
|
||||
let syntax_set_cell = LazyCell::new();
|
||||
if let Some(syntax_set) = syntax_set {
|
||||
syntax_set_cell.fill(syntax_set).expect("can never fail");
|
||||
}
|
||||
|
||||
HighlightingAssets {
|
||||
syntax_set,
|
||||
syntax_set_cell,
|
||||
serialized_syntax_set,
|
||||
theme_set,
|
||||
fallback_theme: None,
|
||||
}
|
||||
@ -97,20 +112,30 @@ impl HighlightingAssets {
|
||||
}
|
||||
|
||||
Ok(HighlightingAssets::new(
|
||||
syntax_set_builder.build(),
|
||||
Some(syntax_set_builder.build()),
|
||||
None,
|
||||
theme_set,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn from_cache(cache_path: &Path) -> Result<Self> {
|
||||
Ok(HighlightingAssets::new(
|
||||
asset_from_cache(&cache_path.join("syntaxes.bin"), "syntax set")?,
|
||||
None,
|
||||
Some(SerializedSyntaxSet::FromFile(
|
||||
cache_path.join("syntaxes.bin"),
|
||||
)),
|
||||
asset_from_cache(&cache_path.join("themes.bin"), "theme set")?,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn from_binary() -> Self {
|
||||
HighlightingAssets::new(get_integrated_syntaxset(), get_integrated_themeset())
|
||||
HighlightingAssets::new(
|
||||
None,
|
||||
Some(SerializedSyntaxSet::FromBinary(
|
||||
get_serialized_integrated_syntaxset(),
|
||||
)),
|
||||
get_integrated_themeset(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn save_to_cache(&self, target_dir: &Path, current_version: &str) -> Result<()> {
|
||||
@ -137,7 +162,17 @@ impl HighlightingAssets {
|
||||
}
|
||||
|
||||
pub(crate) fn get_syntax_set(&self) -> Result<&SyntaxSet> {
|
||||
Ok(&self.syntax_set)
|
||||
if !self.syntax_set_cell.filled() {
|
||||
self.syntax_set_cell.fill(
|
||||
self.serialized_syntax_set
|
||||
.as_ref()
|
||||
.expect("a dev forgot to setup serialized_syntax_set, please report to https://github.com/sharkdp/bat/issues")
|
||||
.deserialize()?
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
// It is safe to .unwrap() because we just made sure it was .filled()
|
||||
Ok(self.syntax_set_cell.borrow().unwrap())
|
||||
}
|
||||
|
||||
/// Use [Self::get_syntaxes] instead
|
||||
@ -316,8 +351,32 @@ impl HighlightingAssets {
|
||||
}
|
||||
}
|
||||
|
||||
/// A SyntaxSet in serialized form, i.e. bincoded and flate2 compressed.
|
||||
/// We keep it in this format since we want to load it lazily.
|
||||
#[derive(Debug)]
|
||||
enum SerializedSyntaxSet {
|
||||
/// The data comes from a user-generated cache file.
|
||||
FromFile(PathBuf),
|
||||
|
||||
/// The data to use is embedded into the bat binary.
|
||||
FromBinary(&'static [u8]),
|
||||
}
|
||||
|
||||
impl SerializedSyntaxSet {
|
||||
fn deserialize(&self) -> Result<SyntaxSet> {
|
||||
match self {
|
||||
SerializedSyntaxSet::FromBinary(data) => Ok(from_binary(data)),
|
||||
SerializedSyntaxSet::FromFile(ref path) => asset_from_cache(&path, "syntax set"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_serialized_integrated_syntaxset() -> &'static [u8] {
|
||||
include_bytes!("../assets/syntaxes.bin")
|
||||
}
|
||||
|
||||
fn get_integrated_syntaxset() -> SyntaxSet {
|
||||
from_binary(include_bytes!("../assets/syntaxes.bin"))
|
||||
from_binary(get_serialized_integrated_syntaxset())
|
||||
}
|
||||
|
||||
fn get_integrated_themeset() -> ThemeSet {
|
||||
|
Loading…
Reference in New Issue
Block a user