perf: remove len field in yspan

This commit is contained in:
Zixuan Chen 2022-11-10 02:27:53 +08:00
parent e3ad3e017d
commit 2c29165ae8
6 changed files with 42 additions and 35 deletions

View file

@ -18,6 +18,12 @@ impl Default for ListSlice {
}
}
impl From<Range<u32>> for ListSlice {
fn from(a: Range<u32>) -> Self {
ListSlice::Slice(a)
}
}
impl ListSlice {
#[inline(always)]
pub fn from_range(range: Range<u32>) -> ListSlice {

View file

@ -72,7 +72,6 @@ impl Tracker {
origin_right: None,
id: ID::unknown(0),
status: Status::new(),
len: init_len as usize,
slice: ListSlice::Unknown(init_len as usize),
},
&mut make_notify(&mut id_to_cursor),
@ -114,7 +113,7 @@ impl Tracker {
let id_span = IdSpan::new(
yspan.id.client_id,
yspan.id.counter,
yspan.len as Counter + yspan.id.counter,
yspan.atom_len() as Counter + yspan.id.counter,
);
let mut len = 0;
for marker in self
@ -126,7 +125,7 @@ impl Tracker {
}
}
assert_eq!(len, yspan.len);
assert_eq!(len, yspan.atom_len());
}
self.content.debug_check();

View file

@ -31,7 +31,6 @@ impl ContentMap {
origin_left: left,
origin_right: right,
id,
len,
status: Default::default(),
slice,
}

View file

@ -91,10 +91,10 @@ impl Marker {
if child.overlap(id_span) {
let start_counter = child.id.counter;
let offset = std::cmp::max(id_span.counter.min() - start_counter, 0);
debug_assert!((offset as usize) < child.len);
debug_assert!((offset as usize) < child.atom_len());
let max_offset = std::cmp::min(
id_span.counter.max() - start_counter,
(child.len - 1) as i32,
(child.atom_len() - 1) as i32,
);
let len = max_offset - offset + 1;
// SAFETY: we just checked it is valid
@ -103,7 +103,7 @@ impl Marker {
*ptr,
i,
offset as usize,
Position::from_offset(offset as isize, child.len),
Position::from_offset(offset as isize, child.atom_len()),
len as usize,
))
})

View file

@ -68,7 +68,6 @@ impl Status {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct YSpan {
pub id: ID,
pub len: usize,
pub status: Status,
pub origin_left: Option<ID>,
pub origin_right: Option<ID>,
@ -76,6 +75,11 @@ pub struct YSpan {
pub slice: ListSlice,
}
#[test]
fn y_span_size() {
println!("{}", std::mem::size_of::<YSpan>());
}
#[derive(Clone, Copy, Debug)]
pub enum StatusChange {
SetAsCurrent,
@ -92,7 +96,7 @@ impl YSpan {
/// this is the last id of the span, which is **included** by self
#[inline]
pub fn last_id(&self) -> ID {
self.id.inc(self.len as i32 - 1)
self.id.inc(self.atom_len() as i32 - 1)
}
#[inline]
@ -104,7 +108,7 @@ impl YSpan {
pub fn contain_id(&self, id: ID) -> bool {
self.id.client_id == id.client_id
&& self.id.counter <= id.counter
&& id.counter < self.id.counter + self.len as i32
&& id.counter < self.id.counter + self.atom_len() as i32
}
#[inline]
@ -113,7 +117,8 @@ impl YSpan {
return false;
}
self.id.counter < id.ctr_end() && self.id.counter + (self.len as Counter) > id.ctr_start()
self.id.counter < id.ctr_end()
&& self.id.counter + (self.atom_len() as Counter) > id.ctr_start()
}
}
@ -121,15 +126,14 @@ impl Mergable for YSpan {
fn is_mergable(&self, other: &Self, _: &()) -> bool {
other.id.client_id == self.id.client_id
&& self.status == other.status
&& self.id.counter + self.len as Counter == other.id.counter
&& self.id.counter + self.atom_len() as Counter == other.id.counter
&& self.origin_right == other.origin_right
&& Some(self.id.inc(self.len as Counter - 1)) == other.origin_left
&& Some(self.id.inc(self.atom_len() as Counter - 1)) == other.origin_left
&& self.slice.is_mergable(&other.slice, &())
}
fn merge(&mut self, other: &Self, _: &()) {
self.origin_right = other.origin_right;
self.len += other.len;
self.slice.merge(&other.slice, &())
}
}
@ -152,7 +156,6 @@ impl Sliceable for YSpan {
origin_left,
origin_right,
id: self.id.inc(from as i32),
len: to - from,
status: self.status.clone(),
slice: self.slice.slice(from, to),
}
@ -166,24 +169,25 @@ impl InsertContentTrait for YSpan {
}
impl HasLength for YSpan {
#[inline]
#[inline(always)]
fn content_len(&self) -> usize {
if self.status.is_activated() {
self.len
self.slice.atom_len()
} else {
0
}
}
#[inline]
#[inline(always)]
fn atom_len(&self) -> usize {
self.len
self.slice.atom_len()
}
}
#[cfg(any(test, features = "fuzzing"))]
pub mod test {
use crate::{
container::text::text_content::ListSlice,
op::{InsertContent, OpContent},
ContentType, Op, ID,
};
@ -201,9 +205,8 @@ pub mod test {
origin_left: Some(ID::new(0, 0)),
origin_right: None,
id: ID::new(0, 1),
len: 1,
status: Default::default(),
slice: Default::default(),
slice: ListSlice::Unknown(1),
})),
},
5,
@ -215,9 +218,8 @@ pub mod test {
origin_left: Some(ID::new(0, 1)),
origin_right: None,
id: ID::new(0, 2),
len: 1,
status: Default::default(),
slice: Default::default(),
slice: ListSlice::Unknown(1),
})),
},
5,
@ -239,9 +241,8 @@ pub mod test {
origin_left: Some(ID::new(0, 0)),
origin_right: None,
id: ID::new(0, 1),
len: 4,
status: Default::default(),
slice: Default::default(),
slice: ListSlice::Unknown(4),
})),
},
5,
@ -253,9 +254,8 @@ pub mod test {
origin_left: Some(ID::new(0, 0)),
origin_right: Some(ID::new(0, 1)),
id: ID::new(0, 5),
len: 4,
status: Default::default(),
slice: Default::default(),
slice: ListSlice::Unknown(4),
})),
},
5,

View file

@ -5,6 +5,7 @@ use crdt_list::{
use rle::{
range_map::{RangeMap, WithStartEnd},
rle_tree::{iter::IterMut, SafeCursorMut},
HasLength,
};
use crate::id::{Counter, ID};
@ -27,7 +28,7 @@ impl OpSet<YSpan, ID> for OpSpanSet {
value.id.into(),
WithStartEnd {
start: value.id.into(),
end: value.id.inc(value.len as i32).into(),
end: value.id.inc(value.atom_len() as i32).into(),
value: true,
},
)
@ -92,7 +93,7 @@ impl ListCrdt for YataImpl {
}
fn contains(op: &Self::OpUnit, id: Self::OpId) -> bool {
op.id.contains(op.len as Counter, id)
op.id.contains(op.atom_len() as Counter, id)
}
}
@ -134,7 +135,10 @@ mod test {
use crdt_list::crdt::OpSet;
use crate::{
container::text::tracker::y_span::{Status, YSpan},
container::text::{
text_content::ListSlice,
tracker::y_span::{Status, YSpan},
},
id::ID,
};
@ -145,11 +149,10 @@ mod test {
let mut set = OpSpanSet::default();
set.insert(&YSpan {
id: ID::new(1, 10),
len: 10,
origin_left: Some(ID::new(0, 1)),
origin_right: Some(ID::new(0, 2)),
status: Status::new(),
slice: Default::default(),
slice: ListSlice::Unknown(10),
});
assert!(set.contain(ID::new(1, 10)));
assert!(set.contain(ID::new(1, 11)));
@ -173,7 +176,7 @@ pub mod fuzz {
fn fields(&self) -> Vec<std::borrow::Cow<'_, str>> {
vec![
self.id.to_string().into(),
self.len.to_string().into(),
self.atom_len().to_string().into(),
self.status.future.to_string().into(),
self.status.delete_times.to_string().into(),
self.status.undo_times.to_string().into(),
@ -202,7 +205,7 @@ pub mod fuzz {
}
use crdt_list::test::{Action, TestFramework};
use rle::{RleVecWithIndex, RleVecWithLen};
use rle::{HasLength, RleVecWithIndex, RleVecWithLen};
use tabled::TableIteratorExt;
use crate::{
@ -221,7 +224,7 @@ pub mod fuzz {
impl TestFramework for YataImpl {
fn integrate(container: &mut Self::Container, op: Self::OpUnit) {
container.head_vv.set_end(op.id.inc(op.len as i32));
container.head_vv.set_end(op.id.inc(op.atom_len() as i32));
// SAFETY: we know this is safe because in [YataImpl::insert_after] there is no access to shared elements
unsafe { crdt_list::yata::integrate::<Self>(container, op) };
}