Skip to content

Commit

Permalink
upgrade syntect to v5, which makes assets loading 1.7x faster
Browse files Browse the repository at this point in the history
```
$ hyperfine 'hgrep hgrep ./README.md' './target/release/hgrep hgrep ./README.md'
Benchmark 1: hgrep hgrep ./README.md
  Time (mean ± σ):      72.3 ms ±   2.5 ms    [User: 67.8 ms, System: 17.2 ms]
  Range (min … max):    70.7 ms …  85.4 ms    40 runs

  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet PC without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.

Benchmark 2: ./target/release/hgrep hgrep ./README.md
  Time (mean ± σ):      42.3 ms ±   0.6 ms    [User: 40.3 ms, System: 14.9 ms]
  Range (min … max):    41.3 ms …  44.6 ms    67 runs

Summary
  './target/release/hgrep hgrep ./README.md' ran
    1.71 ± 0.06 times faster than 'hgrep hgrep ./README.md'
```
  • Loading branch information
rhysd committed Jan 14, 2023
1 parent f6917a2 commit c26db0f
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 32 deletions.
28 changes: 24 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ ignore = { version = "0.4", optional = true }
regex = { version = "1", optional = true }
grep-matcher = { version = "0.1.5", optional = true }
grep-pcre2 = { version = "0.1.5", optional = true }
syntect = { version = "4.6", optional = true }
syntect = { version = "5.0", optional = true }
rayon = { version = "1", optional = true }
unicode-width = { version = "0.1.10", optional = true }
bincode = { version = "1.3", optional = true }
Expand Down
2 changes: 1 addition & 1 deletion assets/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Assets imported from [bat](https://github.com/sharkdp/bat)

`syntaxes.bin` and `ansi.tmTheme` were imported from bat `7be9485c3690799ee204ec5195172f9e90f49924`. They're licensed with
`syntaxes.bin` and `ansi.tmTheme` were imported from bat `362af8a0a65e16189cdcde57ec82d66bb248f3c3`. They're licensed with
[the MIT license](./bat-LICENSE-MIT).

## How to update `syntaxes.bin`
Expand Down
2 changes: 1 addition & 1 deletion assets/builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
syntect = "4.6"
syntect = "5.0"
bincode = "1.3"
flate2 = "1"
path-slash = "0.2"
Binary file modified assets/syntaxes.bin
Binary file not shown.
Binary file modified assets/themes.bin
Binary file not shown.
31 changes: 20 additions & 11 deletions src/io.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::io::{ErrorKind, Result};
use std::io;

pub trait IgnoreBrokenPipe {
fn ignore_broken_pipe(self) -> Self;
}

impl<T: Default> IgnoreBrokenPipe for Result<T> {
impl<T: Default> IgnoreBrokenPipe for io::Result<T> {
fn ignore_broken_pipe(self) -> Self {
self.or_else(|err| {
if err.kind() == ErrorKind::BrokenPipe {
if err.kind() == io::ErrorKind::BrokenPipe {
Ok(T::default())
} else {
Err(err)
Expand All @@ -16,30 +16,39 @@ impl<T: Default> IgnoreBrokenPipe for Result<T> {
}
}

impl<T: Default> IgnoreBrokenPipe for anyhow::Result<T> {
fn ignore_broken_pipe(self) -> Self {
self.or_else(|err| match err.downcast_ref::<io::Error>() {
Some(err) if err.kind() == io::ErrorKind::BrokenPipe => Ok(T::default()),
_ => Err(err),
})
}
}

#[cfg(test)]
mod tests {
use super::*;
use std::io::Error;

#[test]
fn test_ignore_broken_pipe() {
let err = Error::new(ErrorKind::BrokenPipe, "oops");
let res = Result::<i32>::Err(err);
fn test_io_ignore_broken_pipe() {
let err = Error::new(io::ErrorKind::BrokenPipe, "oops");
let res = io::Result::<i32>::Err(err);
let res = res.ignore_broken_pipe();
assert_eq!(res.unwrap(), 0);
}

#[test]
fn test_do_not_ignore_other_errors() {
let err = Error::new(ErrorKind::Other, "oops");
let res = Result::<i32>::Err(err);
fn test_io_do_not_ignore_other_errors() {
let err = Error::new(io::ErrorKind::Other, "oops");
let res = io::Result::<i32>::Err(err);
let res = res.ignore_broken_pipe();
res.unwrap_err();
}

#[test]
fn test_do_nothing_on_ok() {
let res = Result::Ok(0i32);
fn test_io_do_nothing_on_ok() {
let res = io::Result::Ok(0i32);
let res = res.ignore_broken_pipe();
assert_eq!(res.unwrap(), 0);
}
Expand Down
31 changes: 17 additions & 14 deletions src/syntect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn load_bat_themes() -> Result<ThemeSet> {
}

fn load_syntax_set() -> Result<SyntaxSet> {
Ok(bincode::deserialize_from(ZlibDecoder::new(SYNTAX_SET_BIN))?)
Ok(bincode::deserialize_from(SYNTAX_SET_BIN)?)
}

pub trait LockableWrite<'a> {
Expand Down Expand Up @@ -69,7 +69,7 @@ fn list_themes_with_syntaxes<W: Write>(

themes
.iter()
.try_for_each(|(name, theme)| {
.try_for_each(|(name, theme)| -> Result<()> {
let mut drawer = Drawer::new(&mut out, opts, theme, &sample_file.chunks);
drawer.canvas.set_bold()?;
write!(drawer.canvas, "{:?}", name)?;
Expand All @@ -79,7 +79,7 @@ fn list_themes_with_syntaxes<W: Write>(

let hl = LineHighlighter::new(syntax, theme, syntaxes);
drawer.draw_file(&sample_file, hl)?;
writeln!(drawer.canvas)
Ok(writeln!(drawer.canvas)?)
})
.ignore_broken_pipe()?;

Expand Down Expand Up @@ -624,19 +624,21 @@ impl<'a> LineHighlighter<'a> {
}
}

fn skip_line(&mut self, line: &str) {
let ops = self.parse_state.parse_line(line, self.syntaxes);
fn skip_line(&mut self, line: &str) -> Result<()> {
let ops = self.parse_state.parse_line(line, self.syntaxes)?;
for _ in HighlightIterator::new(&mut self.hl_state, &ops, line, &self.hl) {}
Ok(())
}

fn highlight<'line>(&mut self, line: &'line str) -> Vec<Token<'line>> {
let ops = self.parse_state.parse_line(line, self.syntaxes);
HighlightIterator::new(&mut self.hl_state, &ops, line, &self.hl)
fn highlight<'line>(&mut self, line: &'line str) -> Result<Vec<Token<'line>>> {
let ops = self.parse_state.parse_line(line, self.syntaxes)?;
let tokens = HighlightIterator::new(&mut self.hl_state, &ops, line, &self.hl)
.map(|(mut style, text)| {
style.foreground = blend_fg_color(style.foreground, style.background);
Token { style, text }
})
.collect()
.collect();
Ok(tokens)
}
}

Expand Down Expand Up @@ -903,7 +905,7 @@ impl<'file, W: Write> Drawer<'file, W> {
self.canvas.draw_newline()
}

fn draw_body(&mut self, file: &File, mut hl: LineHighlighter<'_>) -> io::Result<()> {
fn draw_body(&mut self, file: &File, mut hl: LineHighlighter<'_>) -> Result<()> {
assert!(!file.chunks.is_empty());

let mut matched = file.line_matches.as_ref();
Expand All @@ -913,7 +915,7 @@ impl<'file, W: Write> Drawer<'file, W> {
for Line(bytes, lnum) in LinesInclusive::new(&file.contents) {
let (start, end) = *chunk;
if lnum < start {
hl.skip_line(String::from_utf8_lossy(bytes).as_ref()); // Discard parsed result
hl.skip_line(String::from_utf8_lossy(bytes).as_ref())?; // Discard parsed result
continue;
}
if start <= lnum && lnum <= end {
Expand All @@ -927,7 +929,7 @@ impl<'file, W: Write> Drawer<'file, W> {
let line = String::from_utf8_lossy(bytes);
// Collect to `Vec` rather than handing HighlightIterator as-is. HighlightIterator takes ownership of Highlighter
// while the iteration. When the highlighter is stored in `self`, it means the iterator takes ownership of `self`.
self.draw_line(hl.highlight(line.as_ref()), lnum, regions)?;
self.draw_line(hl.highlight(line.as_ref())?, lnum, regions)?;

if lnum == end {
if self.first_only {
Expand Down Expand Up @@ -971,10 +973,11 @@ impl<'file, W: Write> Drawer<'file, W> {
Ok(())
}

fn draw_file(&mut self, file: &File, hl: LineHighlighter) -> io::Result<()> {
fn draw_file(&mut self, file: &File, hl: LineHighlighter) -> Result<()> {
self.draw_header(&file.path)?;
self.draw_body(file, hl)?;
self.draw_footer()
self.draw_footer()?;
Ok(())
}
}

Expand Down

0 comments on commit c26db0f

Please sign in to comment.