Skip to content

Commit

Permalink
Optimize rendering by using Ropey::byte_slice
Browse files Browse the repository at this point in the history
This avoids costly conversions via byte_to_char (which are then
reversed back into bytes internally in Ropey).

Reduces time spent in slice/byte_to_char from ~24% to ~5%.
  • Loading branch information
archseer committed Mar 17, 2022
1 parent c6bd105 commit 59f0508
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 17 deletions.
10 changes: 8 additions & 2 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion helix-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ include = ["src/**/*", "README.md"]
[dependencies]
helix-loader = { version = "0.6", path = "../helix-loader" }

ropey = "1.3"
# ropey = "1.3"
ropey = { git = "https://github.com/cessen/ropey" }
smallvec = "1.8"
smartstring = "1.0.0"
unicode-segmentation = "1.9"
Expand Down
5 changes: 1 addition & 4 deletions helix-core/src/graphemes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,10 +333,7 @@ impl<'a> Iterator for RopeGraphemes<'a> {
}

if a < self.cur_chunk_start {
let a_char = self.text.byte_to_char(a);
let b_char = self.text.byte_to_char(b);

Some(self.text.slice(a_char..b_char))
Some(self.text.byte_slice(a..b))
} else {
let a2 = a - self.cur_chunk_start;
let b2 = b - self.cur_chunk_start;
Expand Down
8 changes: 2 additions & 6 deletions helix-core/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,9 +576,7 @@ pub struct Syntax {
}

fn byte_range_to_str(range: std::ops::Range<usize>, source: RopeSlice) -> Cow<str> {
let start_char = source.byte_to_char(range.start);
let end_char = source.byte_to_char(range.end);
Cow::from(source.slice(start_char..end_char))
Cow::from(source.byte_slice(range))
}

impl Syntax {
Expand Down Expand Up @@ -1197,9 +1195,7 @@ impl<'a> TextProvider<'a> for RopeProvider<'a> {
type I = ChunksBytes<'a>;

fn text(&mut self, node: Node) -> Self::I {
let start_char = self.0.byte_to_char(node.start_byte());
let end_char = self.0.byte_to_char(node.end_byte());
let fragment = self.0.slice(start_char..end_char);
let fragment = self.0.byte_slice(node.start_byte()..node.end_byte());
ChunksBytes {
chunks: fragment.chunks(),
}
Expand Down
7 changes: 3 additions & 4 deletions helix-term/src/ui/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ impl EditorView {
.highlight_iter(text.slice(..), Some(range), None)
.map(|event| event.unwrap())
.map(move |event| match event {
// TODO: use byte slices directly
// convert byte offsets to char offset
HighlightEvent::Source { start, end } => {
let start =
Expand Down Expand Up @@ -317,6 +318,8 @@ impl EditorView {
theme: &Theme,
highlights: H,
) {
// It's slightly more efficient to produce a full RopeSlice from the Rope, then slice that a bunch
// of times than it is to always call Rope::slice/get_slice (it will internally always hit RSEnum::Light).
let text = doc.text().slice(..);

let mut spans = Vec::new();
Expand All @@ -327,10 +330,6 @@ impl EditorView {

let text_style = theme.get("ui.text");

// It's slightly more efficient to produce a full RopeSlice from the Rope, then slice that a bunch
// of times than it is to always call Rope::slice/get_slice (it will internally always hit RSEnum::Light).
let text = text.slice(..);

'outer: for event in highlights {
match event {
HighlightEvent::HighlightStart(span) => {
Expand Down

0 comments on commit 59f0508

Please sign in to comment.