text: Actually short circuit anchored_edits_since_in_range (#48486)

Lukas Wirth created

When the version is the same we used to still seek through the
underlying fragment sumtree despite having nothing to return. This has a
lot of unnecessary overhead.

Release Notes:

- N/A *or* Added/Fixed/Improved ...

Change summary

crates/language/src/buffer.rs           |  3 +++
crates/multi_buffer/src/multi_buffer.rs | 16 +++++++++++-----
crates/sum_tree/src/tree_map.rs         |  3 +++
crates/text/src/text.rs                 | 23 ++++++++++++-----------
4 files changed, 29 insertions(+), 16 deletions(-)

Detailed changes

crates/language/src/buffer.rs 🔗

@@ -1480,6 +1480,9 @@ impl Buffer {
         may_block: bool,
         cx: &mut Context<Self>,
     ) {
+        if language == self.language {
+            return;
+        }
         self.non_text_state_update_count += 1;
         self.syntax_map.lock().clear(&self.text);
         let old_language = std::mem::replace(&mut self.language, language);

crates/multi_buffer/src/multi_buffer.rs 🔗

@@ -3052,11 +3052,17 @@ impl MultiBuffer {
             *non_text_state_update_count += 1;
         }
 
-        for (id, diff) in diffs.iter() {
-            if buffer_diff.get(id).is_none() || diff.is_inverted {
-                buffer_diff.insert(*id, diff.snapshot(cx));
-            }
-        }
+        let diffs_to_add = diffs
+            .iter()
+            .filter_map(|(id, diff)| {
+                if diff.is_inverted || buffer_diff.get(id).is_none() {
+                    Some((*id, diff.snapshot(cx)))
+                } else {
+                    None
+                }
+            })
+            .collect::<Vec<_>>();
+        buffer_diff.extend(diffs_to_add);
 
         excerpts_to_edit.sort_unstable_by_key(|(locator, _, _)| *locator);
 

crates/sum_tree/src/tree_map.rs 🔗

@@ -83,6 +83,9 @@ impl<K: Clone + Ord, V: Clone> TreeMap<K, V> {
             .into_iter()
             .map(|(key, value)| Edit::Insert(MapEntry { key, value }))
             .collect();
+        if edits.is_empty() {
+            return;
+        }
         self.0.edit(edits, ());
     }
 

crates/text/src/text.rs 🔗

@@ -2508,15 +2508,14 @@ impl BufferSnapshot {
     where
         D: TextDimension + Ord,
     {
-        let fragments_cursor = if *since == self.version {
-            None
-        } else {
-            let mut cursor = self.fragments.filter(&None, move |summary| {
-                !since.observed_all(&summary.max_version)
-            });
-            cursor.next();
-            Some(cursor)
-        };
+        if *since == self.version {
+            return None.into_iter().flatten();
+        }
+        let mut cursor = self.fragments.filter(&None, move |summary| {
+            !since.observed_all(&summary.max_version)
+        });
+        cursor.next();
+        let fragments_cursor = Some(cursor);
         let start_fragment_id = self.fragment_id_for_anchor(&range.start);
         let (start, _, item) = self
             .fragments
@@ -2537,7 +2536,7 @@ impl BufferSnapshot {
         }
         let end_fragment_id = self.fragment_id_for_anchor(&range.end);
 
-        Edits {
+        Some(Edits {
             visible_cursor: self.visible_text.cursor(visible_start),
             deleted_cursor: self.deleted_text.cursor(deleted_start),
             fragments_cursor,
@@ -2547,7 +2546,9 @@ impl BufferSnapshot {
             new_end: D::zero(()),
             range: (start_fragment_id, range.start.offset)..(end_fragment_id, range.end.offset),
             buffer_id: self.remote_id,
-        }
+        })
+        .into_iter()
+        .flatten()
     }
 
     pub fn has_edits_since_in_range(&self, since: &clock::Global, range: Range<Anchor>) -> bool {