editor: Reduce amount of sumtree traversals in header_and_footer_blocks (#43709)
Introduces new "mapping point cursors" for the different display map layers allowing one to map multiple points in increasing order more efficiently than using the one shot operations. This is used in the `BlockMap::sync` for `header_and_footer_blocks` which spends a significant time in sumtree traversal due to repeatedly transforming points between the different layers. This effectively turns the complexity of those operations from quadratic in the number of excerpts to linear, as we only go through the respective sumtrees once instead of restarting from the start over and over again. Release Notes: - Improved performance for editors of large multibuffers with many different files
This commit is contained in:
@@ -879,37 +879,16 @@ impl InlaySnapshot {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_inlay_point(&self, point: Point) -> InlayPoint {
|
||||
let mut cursor = self.transforms.cursor::<Dimensions<Point, InlayPoint>>(());
|
||||
cursor.seek(&point, Bias::Left);
|
||||
loop {
|
||||
match cursor.item() {
|
||||
Some(Transform::Isomorphic(_)) => {
|
||||
if point == cursor.end().0 {
|
||||
while let Some(Transform::Inlay(inlay)) = cursor.next_item() {
|
||||
if inlay.position.bias() == Bias::Right {
|
||||
break;
|
||||
} else {
|
||||
cursor.next();
|
||||
}
|
||||
}
|
||||
return cursor.end().1;
|
||||
} else {
|
||||
let overshoot = point - cursor.start().0;
|
||||
return InlayPoint(cursor.start().1.0 + overshoot);
|
||||
}
|
||||
}
|
||||
Some(Transform::Inlay(inlay)) => {
|
||||
if inlay.position.bias() == Bias::Left {
|
||||
cursor.next();
|
||||
} else {
|
||||
return cursor.start().1;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
return self.max_point();
|
||||
}
|
||||
}
|
||||
self.inlay_point_cursor().map(point)
|
||||
}
|
||||
|
||||
pub fn inlay_point_cursor(&self) -> InlayPointCursor<'_> {
|
||||
let cursor = self.transforms.cursor::<Dimensions<Point, InlayPoint>>(());
|
||||
InlayPointCursor {
|
||||
cursor,
|
||||
transforms: &self.transforms,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1162,6 +1141,51 @@ impl InlaySnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InlayPointCursor<'transforms> {
|
||||
cursor: Cursor<'transforms, 'static, Transform, Dimensions<Point, InlayPoint>>,
|
||||
transforms: &'transforms SumTree<Transform>,
|
||||
}
|
||||
|
||||
impl InlayPointCursor<'_> {
|
||||
pub fn map(&mut self, point: Point) -> InlayPoint {
|
||||
let cursor = &mut self.cursor;
|
||||
if cursor.did_seek() {
|
||||
cursor.seek_forward(&point, Bias::Left);
|
||||
} else {
|
||||
cursor.seek(&point, Bias::Left);
|
||||
}
|
||||
loop {
|
||||
match cursor.item() {
|
||||
Some(Transform::Isomorphic(_)) => {
|
||||
if point == cursor.end().0 {
|
||||
while let Some(Transform::Inlay(inlay)) = cursor.next_item() {
|
||||
if inlay.position.bias() == Bias::Right {
|
||||
break;
|
||||
} else {
|
||||
cursor.next();
|
||||
}
|
||||
}
|
||||
return cursor.end().1;
|
||||
} else {
|
||||
let overshoot = point - cursor.start().0;
|
||||
return InlayPoint(cursor.start().1.0 + overshoot);
|
||||
}
|
||||
}
|
||||
Some(Transform::Inlay(inlay)) => {
|
||||
if inlay.position.bias() == Bias::Left {
|
||||
cursor.next();
|
||||
} else {
|
||||
return cursor.start().1;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
return InlayPoint(self.transforms.summary().output.lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn push_isomorphic(sum_tree: &mut SumTree<Transform>, summary: MBTextSummary) {
|
||||
if summary.len == MultiBufferOffset(0) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user