Optimize anchor comparison and take full advantage of fragment IDs

Antonio Scandurra created

Change summary

Cargo.lock                 |  1 +
crates/text/Cargo.toml     |  1 +
crates/text/src/anchor.rs  | 12 +++++++-----
crates/text/src/locator.rs |  6 ++++++
crates/text/src/text.rs    | 12 ++++--------
5 files changed, 19 insertions(+), 13 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -4853,6 +4853,7 @@ dependencies = [
  "ctor",
  "env_logger",
  "gpui",
+ "lazy_static",
  "log",
  "parking_lot",
  "rand 0.8.3",

crates/text/Cargo.toml 🔗

@@ -15,6 +15,7 @@ collections = { path = "../collections" }
 sum_tree = { path = "../sum_tree" }
 anyhow = "1.0.38"
 arrayvec = "0.7.1"
+lazy_static = "1.4"
 log = "0.4"
 parking_lot = "0.11"
 rand = { version = "0.8.3", optional = true }

crates/text/src/anchor.rs 🔗

@@ -28,15 +28,17 @@ impl Anchor {
     }
 
     pub fn cmp<'a>(&self, other: &Anchor, buffer: &Snapshot) -> Result<Ordering> {
-        let offset_comparison = if self.timestamp == other.timestamp {
-            self.offset.cmp(&other.offset)
+        let fragment_id_comparison = if self.timestamp == other.timestamp {
+            Ordering::Equal
         } else {
             buffer
-                .full_offset_for_anchor(self)
-                .cmp(&buffer.full_offset_for_anchor(other))
+                .fragment_id_for_anchor(self)
+                .cmp(&buffer.fragment_id_for_anchor(other))
         };
 
-        Ok(offset_comparison.then_with(|| self.bias.cmp(&other.bias)))
+        Ok(fragment_id_comparison
+            .then_with(|| self.offset.cmp(&other.offset))
+            .then_with(|| self.bias.cmp(&other.bias)))
     }
 
     pub fn bias_left(&self, buffer: &Buffer) -> Anchor {

crates/text/src/locator.rs 🔗

@@ -1,6 +1,12 @@
+use lazy_static::lazy_static;
 use smallvec::{smallvec, SmallVec};
 use std::iter;
 
+lazy_static! {
+    pub static ref MIN: Locator = Locator::min();
+    pub static ref MAX: Locator = Locator::max();
+}
+
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct Locator(SmallVec<[u64; 4]>);
 

crates/text/src/text.rs 🔗

@@ -1763,12 +1763,11 @@ impl Snapshot {
         }
     }
 
-    fn full_offset_for_anchor(&self, anchor: &Anchor) -> FullOffset {
+    fn fragment_id_for_anchor(&self, anchor: &Anchor) -> &Locator {
         if *anchor == Anchor::min() {
-            Default::default()
+            &locator::MIN
         } else if *anchor == Anchor::max() {
-            let text = self.fragments.summary().text;
-            FullOffset(text.visible + text.deleted)
+            &locator::MAX
         } else {
             let anchor_key = InsertionFragmentKey {
                 timestamp: anchor.timestamp,
@@ -1790,10 +1789,7 @@ impl Snapshot {
             }
             let insertion = insertion_cursor.item().expect("invalid insertion");
             debug_assert_eq!(insertion.timestamp, anchor.timestamp, "invalid insertion");
-
-            let mut fragment_cursor = self.fragments.cursor::<(Option<&Locator>, FullOffset)>();
-            fragment_cursor.seek(&Some(&insertion.fragment_id), Bias::Left, &None);
-            fragment_cursor.start().1 + (anchor.offset - insertion.split_offset)
+            &insertion.fragment_id
         }
     }