From af4c4c7cf032d41d437fce68e0bdfa42b070b3fc Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 30 Mar 2023 10:03:13 +0200 Subject: [PATCH] Speed up tab searching in `TabMap::sync` by looking for `\t` only Instead of looking for `\n` as a stopping condition, we cap the range we pass to `SuggestionSnapshot::chunks` to stop on the next line. This makes character searching faster, because looking for a single character uses `memchr`. Also, this avoids an extra conditional in a tight loop such as the chunk scanning one contained in `TabMap::sync`. --- crates/editor/src/display_map/tab_map.rs | 52 +++++++++++------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/crates/editor/src/display_map/tab_map.rs b/crates/editor/src/display_map/tab_map.rs index 8c136f4b18..2299edf61e 100644 --- a/crates/editor/src/display_map/tab_map.rs +++ b/crates/editor/src/display_map/tab_map.rs @@ -47,7 +47,6 @@ impl TabMap { new_snapshot.version += 1; } - let old_max_offset = old_snapshot.suggestion_snapshot.len(); let mut tab_edits = Vec::with_capacity(suggestion_edits.len()); if old_snapshot.tab_size == new_snapshot.tab_size { @@ -55,49 +54,46 @@ impl TabMap { // and any subsequent tabs on that line that moved across the tab expansion // boundary. for suggestion_edit in &mut suggestion_edits { - let old_end_column = old_snapshot + let old_end = old_snapshot .suggestion_snapshot - .to_point(suggestion_edit.old.end) - .column(); - let new_end_column = new_snapshot + .to_point(suggestion_edit.old.end); + let old_end_row_successor_offset = + old_snapshot.suggestion_snapshot.to_offset(cmp::min( + SuggestionPoint::new(old_end.row() + 1, 0), + old_snapshot.suggestion_snapshot.max_point(), + )); + let new_end = new_snapshot .suggestion_snapshot - .to_point(suggestion_edit.new.end) - .column(); + .to_point(suggestion_edit.new.end); let mut offset_from_edit = 0; let mut first_tab_offset = None; let mut last_tab_with_changed_expansion_offset = None; 'outer: for chunk in old_snapshot.suggestion_snapshot.chunks( - suggestion_edit.old.end..old_max_offset, + suggestion_edit.old.end..old_end_row_successor_offset, false, None, ) { - for (ix, mat) in chunk.text.match_indices(&['\t', '\n']) { + for (ix, _) in chunk.text.match_indices('\t') { let offset_from_edit = offset_from_edit + (ix as u32); - match mat { - "\t" => { - if first_tab_offset.is_none() { - first_tab_offset = Some(offset_from_edit); - } + if first_tab_offset.is_none() { + first_tab_offset = Some(offset_from_edit); + } - let old_column = old_end_column + offset_from_edit; - let new_column = new_end_column + offset_from_edit; - let was_expanded = old_column < old_snapshot.max_expansion_column; - let is_expanded = new_column < new_snapshot.max_expansion_column; - if was_expanded != is_expanded { - last_tab_with_changed_expansion_offset = Some(offset_from_edit); - } else if !was_expanded && !is_expanded { - break 'outer; - } - } - "\n" => break 'outer, - _ => unreachable!(), + let old_column = old_end.column() + offset_from_edit; + let new_column = new_end.column() + offset_from_edit; + let was_expanded = old_column < old_snapshot.max_expansion_column; + let is_expanded = new_column < new_snapshot.max_expansion_column; + if was_expanded != is_expanded { + last_tab_with_changed_expansion_offset = Some(offset_from_edit); + } else if !was_expanded && !is_expanded { + break 'outer; } } offset_from_edit += chunk.text.len() as u32; - if old_end_column + offset_from_edit >= old_snapshot.max_expansion_column - && new_end_column + offset_from_edit >= new_snapshot.max_expansion_column + if old_end.column() + offset_from_edit >= old_snapshot.max_expansion_column + && new_end.column() + offset_from_edit >= new_snapshot.max_expansion_column { break; }