mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
Speed up is_dirty and has_conflict (#11946)
I noticed that scrolling the assistant panel was very slow in debug mode, after running a completion. From profiling, I saw that it was due to the buffer's `is_dirty` and `has_conflict` checks, which use `edits_since` to check if there are any non-undone edits since the saved version. I optimized this in two ways: * I introduced a specialized `has_edits_since` method on text buffers, which allows us to more cheaply check if the buffer has been edited since a given version, without some of the overhead involved in computing what the edits actually are. * In the case of `has_conflict`, we don't even need to call that method in the case where the buffer doesn't have a file (is untitled, as is the case in the assistant panel). Buffers without files cannot be in conflict. Release Notes: - Improved performance of editing the assistant panel and untitled buffers with many edits.
This commit is contained in:
parent
23315d214c
commit
df3bd40c56
@ -1527,14 +1527,10 @@ impl Buffer {
|
||||
self.end_transaction(cx)
|
||||
}
|
||||
|
||||
fn changed_since_saved_version(&self) -> bool {
|
||||
self.edits_since::<usize>(&self.saved_version)
|
||||
.next()
|
||||
.is_some()
|
||||
}
|
||||
/// Checks if the buffer has unsaved changes.
|
||||
pub fn is_dirty(&self) -> bool {
|
||||
(self.has_conflict || self.changed_since_saved_version())
|
||||
self.has_conflict
|
||||
|| self.has_edits_since(&self.saved_version)
|
||||
|| self
|
||||
.file
|
||||
.as_ref()
|
||||
@ -1544,11 +1540,10 @@ impl Buffer {
|
||||
/// Checks if the buffer and its file have both changed since the buffer
|
||||
/// was last saved or reloaded.
|
||||
pub fn has_conflict(&self) -> bool {
|
||||
(self.has_conflict || self.changed_since_saved_version())
|
||||
&& self
|
||||
.file
|
||||
.as_ref()
|
||||
.map_or(false, |file| file.mtime() > self.saved_mtime)
|
||||
self.has_conflict
|
||||
|| self.file.as_ref().map_or(false, |file| {
|
||||
file.mtime() > self.saved_mtime && self.has_edits_since(&self.saved_version)
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets a [`Subscription`] that tracks all of the changes to the buffer's text.
|
||||
|
@ -139,6 +139,14 @@ fn test_random_edits(mut rng: StdRng) {
|
||||
assert_eq!(old_text, new_text);
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
buffer.has_edits_since(&old_buffer.version),
|
||||
buffer
|
||||
.edits_since::<usize>(&old_buffer.version)
|
||||
.next()
|
||||
.is_some(),
|
||||
);
|
||||
|
||||
let subscription_edits = subscription.consume();
|
||||
log::info!(
|
||||
"applying subscription edits since version {:?} to old text: {:?}: {:?}",
|
||||
|
@ -2165,6 +2165,24 @@ impl BufferSnapshot {
|
||||
buffer_id: self.remote_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_edits_since(&self, since: &clock::Global) -> bool {
|
||||
if *since != self.version {
|
||||
let mut cursor = self
|
||||
.fragments
|
||||
.filter::<_, usize>(move |summary| !since.observed_all(&summary.max_version));
|
||||
cursor.next(&None);
|
||||
while let Some(fragment) = cursor.item() {
|
||||
let was_visible = fragment.was_visible(since, &self.undo_map);
|
||||
let is_visible = fragment.visible;
|
||||
if was_visible != is_visible {
|
||||
return true;
|
||||
}
|
||||
cursor.next(&None);
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct RopeBuilder<'a> {
|
||||
|
Loading…
Reference in New Issue
Block a user