mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-25 01:34:02 +00:00
Reduce Fragment
size by not storing ReplicaId
twice
This commit is contained in:
parent
8f8c6c8add
commit
5d1afaf484
1 changed files with 65 additions and 54 deletions
|
@ -169,7 +169,7 @@ impl History {
|
|||
}
|
||||
|
||||
fn push(&mut self, op: EditOperation) {
|
||||
self.ops.insert(op.id, op);
|
||||
self.ops.insert(op.timestamp.local(), op);
|
||||
}
|
||||
|
||||
fn start_transaction(
|
||||
|
@ -326,12 +326,34 @@ struct Diff {
|
|||
changes: Vec<(ChangeTag, usize)>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
struct InsertionTimestamp {
|
||||
replica_id: ReplicaId,
|
||||
local: time::Seq,
|
||||
lamport: time::Seq,
|
||||
}
|
||||
|
||||
impl InsertionTimestamp {
|
||||
fn local(&self) -> time::Local {
|
||||
time::Local {
|
||||
replica_id: self.replica_id,
|
||||
value: self.local,
|
||||
}
|
||||
}
|
||||
|
||||
fn lamport(&self) -> time::Lamport {
|
||||
time::Lamport {
|
||||
replica_id: self.replica_id,
|
||||
value: self.lamport,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||
struct Fragment {
|
||||
timestamp: InsertionTimestamp,
|
||||
len: usize,
|
||||
visible: bool,
|
||||
insertion_id: time::Local,
|
||||
lamport_timestamp: time::Lamport,
|
||||
deletions: HashSet<time::Local>,
|
||||
max_undos: time::Global,
|
||||
}
|
||||
|
@ -359,10 +381,7 @@ impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FragmentTextSummary {
|
|||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Operation {
|
||||
Edit {
|
||||
edit: EditOperation,
|
||||
lamport_timestamp: time::Lamport,
|
||||
},
|
||||
Edit(EditOperation),
|
||||
Undo {
|
||||
undo: UndoOperation,
|
||||
lamport_timestamp: time::Lamport,
|
||||
|
@ -376,7 +395,7 @@ pub enum Operation {
|
|||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct EditOperation {
|
||||
id: time::Local,
|
||||
timestamp: InsertionTimestamp,
|
||||
version: time::Global,
|
||||
ranges: Vec<Range<usize>>,
|
||||
new_text: Option<String>,
|
||||
|
@ -457,12 +476,11 @@ impl Buffer {
|
|||
if visible_text.len() > 0 {
|
||||
fragments.push(
|
||||
Fragment {
|
||||
insertion_id: Default::default(),
|
||||
lamport_timestamp: Default::default(),
|
||||
timestamp: Default::default(),
|
||||
len: visible_text.len(),
|
||||
visible: true,
|
||||
deletions: Default::default(),
|
||||
max_undos: Default::default(),
|
||||
visible: true,
|
||||
},
|
||||
&None,
|
||||
);
|
||||
|
@ -932,21 +950,21 @@ impl Buffer {
|
|||
None
|
||||
} else {
|
||||
self.start_transaction_at(None, Instant::now()).unwrap();
|
||||
let edit_id = self.local_clock.tick();
|
||||
let lamport_timestamp = self.lamport_clock.tick();
|
||||
let edit = self.apply_local_edit(&ranges, new_text, edit_id, lamport_timestamp);
|
||||
let timestamp = InsertionTimestamp {
|
||||
replica_id: self.replica_id,
|
||||
local: self.local_clock.tick().value,
|
||||
lamport: self.lamport_clock.tick().value,
|
||||
};
|
||||
let edit = self.apply_local_edit(&ranges, new_text, timestamp);
|
||||
|
||||
self.history.push(edit.clone());
|
||||
self.history.push_undo(edit.id);
|
||||
self.last_edit = edit.id;
|
||||
self.version.observe(edit.id);
|
||||
self.history.push_undo(edit.timestamp.local());
|
||||
self.last_edit = edit.timestamp.local();
|
||||
self.version.observe(edit.timestamp.local());
|
||||
|
||||
self.end_transaction_at(None, Instant::now(), cx).unwrap();
|
||||
|
||||
Some(Operation::Edit {
|
||||
edit,
|
||||
lamport_timestamp,
|
||||
})
|
||||
Some(Operation::Edit(edit))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1067,20 +1085,15 @@ impl Buffer {
|
|||
|
||||
fn apply_op(&mut self, op: Operation) -> Result<()> {
|
||||
match op {
|
||||
Operation::Edit {
|
||||
edit,
|
||||
lamport_timestamp,
|
||||
..
|
||||
} => {
|
||||
if !self.version.observed(edit.id) {
|
||||
Operation::Edit(edit) => {
|
||||
if !self.version.observed(edit.timestamp.local()) {
|
||||
self.apply_remote_edit(
|
||||
&edit.version,
|
||||
&edit.ranges,
|
||||
edit.new_text.as_deref(),
|
||||
edit.id,
|
||||
lamport_timestamp,
|
||||
edit.timestamp,
|
||||
);
|
||||
self.version.observe(edit.id);
|
||||
self.version.observe(edit.timestamp.local());
|
||||
self.history.push(edit);
|
||||
}
|
||||
}
|
||||
|
@ -1116,8 +1129,7 @@ impl Buffer {
|
|||
version: &time::Global,
|
||||
ranges: &[Range<usize>],
|
||||
new_text: Option<&str>,
|
||||
local_timestamp: time::Local,
|
||||
lamport_timestamp: time::Lamport,
|
||||
timestamp: InsertionTimestamp,
|
||||
) {
|
||||
if ranges.is_empty() {
|
||||
return;
|
||||
|
@ -1171,7 +1183,9 @@ impl Buffer {
|
|||
// Skip over insertions that are concurrent to this edit, but have a lower lamport
|
||||
// timestamp.
|
||||
while let Some(fragment) = old_fragments.item() {
|
||||
if fragment_start == range.start && fragment.lamport_timestamp > lamport_timestamp {
|
||||
if fragment_start == range.start
|
||||
&& fragment.timestamp.lamport() > timestamp.lamport()
|
||||
{
|
||||
new_ropes.push_fragment(fragment, fragment.visible);
|
||||
new_fragments.push(fragment.clone(), &None);
|
||||
old_fragments.next(&cx);
|
||||
|
@ -1196,8 +1210,7 @@ impl Buffer {
|
|||
new_ropes.push_str(new_text);
|
||||
new_fragments.push(
|
||||
Fragment {
|
||||
insertion_id: local_timestamp,
|
||||
lamport_timestamp,
|
||||
timestamp,
|
||||
len: new_text.len(),
|
||||
deletions: Default::default(),
|
||||
max_undos: Default::default(),
|
||||
|
@ -1216,7 +1229,7 @@ impl Buffer {
|
|||
let intersection_end = cmp::min(range.end, fragment_end);
|
||||
if fragment.was_visible(version, &self.undo_map) {
|
||||
intersection.len = intersection_end - fragment_start;
|
||||
intersection.deletions.insert(local_timestamp);
|
||||
intersection.deletions.insert(timestamp.local());
|
||||
intersection.visible = false;
|
||||
}
|
||||
if intersection.len > 0 {
|
||||
|
@ -1252,8 +1265,8 @@ impl Buffer {
|
|||
self.fragments = new_fragments;
|
||||
self.visible_text = visible_text;
|
||||
self.deleted_text = deleted_text;
|
||||
self.local_clock.observe(local_timestamp);
|
||||
self.lamport_clock.observe(lamport_timestamp);
|
||||
self.local_clock.observe(timestamp.local());
|
||||
self.lamport_clock.observe(timestamp.lamport());
|
||||
}
|
||||
|
||||
pub fn undo(&mut self, mut cx: Option<&mut ModelContext<Self>>) -> Vec<Operation> {
|
||||
|
@ -1355,7 +1368,7 @@ impl Buffer {
|
|||
let mut fragment = fragment.clone();
|
||||
let fragment_was_visible = fragment.visible;
|
||||
if fragment.was_visible(&edit.version, &self.undo_map)
|
||||
|| fragment.insertion_id == edit.id
|
||||
|| fragment.timestamp.local() == edit.timestamp.local()
|
||||
{
|
||||
fragment.visible = fragment.is_visible(&self.undo_map);
|
||||
fragment.max_undos.observe(undo.id);
|
||||
|
@ -1403,7 +1416,7 @@ impl Buffer {
|
|||
false
|
||||
} else {
|
||||
match op {
|
||||
Operation::Edit { edit, .. } => self.version >= edit.version,
|
||||
Operation::Edit(edit) => self.version >= edit.version,
|
||||
Operation::Undo { undo, .. } => self.version.observed(undo.edit_id),
|
||||
Operation::UpdateSelections { selections, .. } => {
|
||||
if let Some(selections) = selections {
|
||||
|
@ -1430,11 +1443,10 @@ impl Buffer {
|
|||
&mut self,
|
||||
ranges: &[Range<usize>],
|
||||
new_text: Option<String>,
|
||||
local_timestamp: time::Local,
|
||||
lamport_timestamp: time::Lamport,
|
||||
timestamp: InsertionTimestamp,
|
||||
) -> EditOperation {
|
||||
let mut edit = EditOperation {
|
||||
id: local_timestamp,
|
||||
timestamp,
|
||||
version: self.version(),
|
||||
ranges: Vec::with_capacity(ranges.len()),
|
||||
new_text: None,
|
||||
|
@ -1487,8 +1499,7 @@ impl Buffer {
|
|||
new_ropes.push_str(new_text);
|
||||
new_fragments.push(
|
||||
Fragment {
|
||||
insertion_id: local_timestamp,
|
||||
lamport_timestamp,
|
||||
timestamp,
|
||||
len: new_text.len(),
|
||||
deletions: Default::default(),
|
||||
max_undos: Default::default(),
|
||||
|
@ -1507,7 +1518,7 @@ impl Buffer {
|
|||
let intersection_end = cmp::min(range.end, fragment_end);
|
||||
if fragment.visible {
|
||||
intersection.len = intersection_end - fragment_start;
|
||||
intersection.deletions.insert(local_timestamp);
|
||||
intersection.deletions.insert(timestamp.local());
|
||||
intersection.visible = false;
|
||||
}
|
||||
if intersection.len > 0 {
|
||||
|
@ -1987,11 +1998,13 @@ impl<'a> Iterator for HighlightedChunks<'a> {
|
|||
|
||||
impl Fragment {
|
||||
fn is_visible(&self, undos: &UndoMap) -> bool {
|
||||
!undos.is_undone(self.insertion_id) && self.deletions.iter().all(|d| undos.is_undone(*d))
|
||||
!undos.is_undone(self.timestamp.local())
|
||||
&& self.deletions.iter().all(|d| undos.is_undone(*d))
|
||||
}
|
||||
|
||||
fn was_visible(&self, version: &time::Global, undos: &UndoMap) -> bool {
|
||||
(version.observed(self.insertion_id) && !undos.was_undone(self.insertion_id, version))
|
||||
(version.observed(self.timestamp.local())
|
||||
&& !undos.was_undone(self.timestamp.local(), version))
|
||||
&& self
|
||||
.deletions
|
||||
.iter()
|
||||
|
@ -2004,14 +2017,14 @@ impl sum_tree::Item for Fragment {
|
|||
|
||||
fn summary(&self) -> Self::Summary {
|
||||
let mut max_version = time::Global::new();
|
||||
max_version.observe(self.insertion_id);
|
||||
max_version.observe(self.timestamp.local());
|
||||
for deletion in &self.deletions {
|
||||
max_version.observe(*deletion);
|
||||
}
|
||||
max_version.join(&self.max_undos);
|
||||
|
||||
let mut min_insertion_version = time::Global::new();
|
||||
min_insertion_version.observe(self.insertion_id);
|
||||
min_insertion_version.observe(self.timestamp.local());
|
||||
let max_insertion_version = min_insertion_version.clone();
|
||||
if self.visible {
|
||||
FragmentSummary {
|
||||
|
@ -2124,9 +2137,7 @@ impl Operation {
|
|||
|
||||
fn lamport_timestamp(&self) -> time::Lamport {
|
||||
match self {
|
||||
Operation::Edit {
|
||||
lamport_timestamp, ..
|
||||
} => *lamport_timestamp,
|
||||
Operation::Edit(edit) => edit.timestamp.lamport(),
|
||||
Operation::Undo {
|
||||
lamport_timestamp, ..
|
||||
} => *lamport_timestamp,
|
||||
|
@ -3474,7 +3485,7 @@ mod tests {
|
|||
impl Operation {
|
||||
fn edit_id(&self) -> Option<time::Local> {
|
||||
match self {
|
||||
Operation::Edit { edit, .. } => Some(edit.id),
|
||||
Operation::Edit(edit) => Some(edit.timestamp.local()),
|
||||
Operation::Undo { undo, .. } => Some(undo.edit_id),
|
||||
Operation::UpdateSelections { .. } => None,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue