Optimize rendering by using Ropey::byte_slice

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%.
pull/1826/head
Blaž Hrastnik 3 years ago
parent c6bd105484
commit 59f05088b9
No known key found for this signature in database
GPG Key ID: 1238B9C4AD889640

10
Cargo.lock generated

@ -862,10 +862,10 @@ checksum = "8c31b5c4033f8fdde8700e4657be2c497e7288f01515be52168c631e2e4d4086"
[[package]]
name = "ropey"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6b9aa65bcd9f308d37c7158b4a1afaaa32b8450213e20c9b98e7d5b3cc2fec3"
source = "git+https://github.com/cessen/ropey#38531e083f8cf5c5b1aeb328361895fb5a9b867c"
dependencies = [
"smallvec",
"str_indices",
]
[[package]]
@ -1031,6 +1031,12 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a"
[[package]]
name = "str_indices"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "283baa48c486e4c5e27b4d92c435db9eaceac236a74dab5e3293570e2c3fa4aa"
[[package]]
name = "syn"
version = "1.0.88"

@ -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"

@ -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;

@ -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 {
@ -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(),
}

@ -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 =
@ -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();
@ -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) => {

Loading…
Cancel
Save