mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-25 09:23:44 +03:00
language: Memoize value of has_edits_since for a given buffer version (#13656)
As a drive-by of https://github.com/zed-industries/zed/pull/13654, I've noticed that the editor felt sluggish after I've undone the changes made by the replacement. It turns out that we are repeatedly checking whether there are any edits to estabilish dirty/conflict state of a buffer, even though this operation is pure; this PR stores away the result of a computation and refers to it before rerunning it. Release Notes: - Improve editor's performance with large undo histories
This commit is contained in:
parent
0761383752
commit
218629cdd4
@ -31,6 +31,7 @@ use smallvec::SmallVec;
|
||||
use smol::future::yield_now;
|
||||
use std::{
|
||||
any::Any,
|
||||
cell::Cell,
|
||||
cmp::{self, Ordering},
|
||||
collections::BTreeMap,
|
||||
ffi::OsStr,
|
||||
@ -113,6 +114,9 @@ pub struct Buffer {
|
||||
capability: Capability,
|
||||
has_conflict: bool,
|
||||
diff_base_version: usize,
|
||||
/// Memoize calls to has_changes_since(saved_version).
|
||||
/// The contents of a cell are (self.version, has_changes) at the time of a last call.
|
||||
has_unsaved_edits: Cell<(clock::Global, bool)>,
|
||||
}
|
||||
|
||||
/// An immutable, cheaply cloneable representation of a fixed
|
||||
@ -690,6 +694,7 @@ impl Buffer {
|
||||
reload_task: None,
|
||||
transaction_depth: 0,
|
||||
was_dirty_before_starting_transaction: None,
|
||||
has_unsaved_edits: Cell::new((buffer.version(), false)),
|
||||
text: buffer,
|
||||
diff_base: diff_base
|
||||
.map(|mut raw_diff_base| {
|
||||
@ -799,6 +804,8 @@ impl Buffer {
|
||||
cx: &mut ModelContext<Self>,
|
||||
) {
|
||||
self.saved_version = version;
|
||||
self.has_unsaved_edits
|
||||
.set((self.saved_version().clone(), false));
|
||||
self.has_conflict = false;
|
||||
self.saved_mtime = mtime;
|
||||
cx.emit(Event::Saved);
|
||||
@ -860,6 +867,8 @@ impl Buffer {
|
||||
cx: &mut ModelContext<Self>,
|
||||
) {
|
||||
self.saved_version = version;
|
||||
self.has_unsaved_edits
|
||||
.set((self.saved_version.clone(), false));
|
||||
self.text.set_line_ending(line_ending);
|
||||
self.saved_mtime = mtime;
|
||||
cx.emit(Event::Reloaded);
|
||||
@ -1516,10 +1525,25 @@ impl Buffer {
|
||||
self.end_transaction(cx)
|
||||
}
|
||||
|
||||
fn has_unsaved_edits(&self) -> bool {
|
||||
let (last_version, has_unsaved_edits) = self.has_unsaved_edits.take();
|
||||
|
||||
if last_version == self.version {
|
||||
self.has_unsaved_edits
|
||||
.set((last_version, has_unsaved_edits));
|
||||
return has_unsaved_edits;
|
||||
}
|
||||
|
||||
let has_edits = self.has_edits_since(&self.saved_version);
|
||||
self.has_unsaved_edits
|
||||
.set((self.version.clone(), has_edits));
|
||||
has_edits
|
||||
}
|
||||
|
||||
/// Checks if the buffer has unsaved changes.
|
||||
pub fn is_dirty(&self) -> bool {
|
||||
self.has_conflict
|
||||
|| self.has_edits_since(&self.saved_version)
|
||||
|| self.has_unsaved_edits()
|
||||
|| self
|
||||
.file
|
||||
.as_ref()
|
||||
@ -1531,7 +1555,7 @@ impl Buffer {
|
||||
pub fn has_conflict(&self) -> bool {
|
||||
self.has_conflict
|
||||
|| self.file.as_ref().map_or(false, |file| {
|
||||
file.mtime() > self.saved_mtime && self.has_edits_since(&self.saved_version)
|
||||
file.mtime() > self.saved_mtime && self.has_unsaved_edits()
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user