WIP: Improve performance of Wrap Map (#16761)
We've ran into performance issues when reinserting new blocks into the assistant panel; in profiles WrapMap showed up, as we try to query wrap boundaries over and over, which is a hidden O(n^2) - for each block, we may potentially look at all of the Wraps. This PR alleviates this issue by storing away previously resolved wrap range; consecutive iterations can often reuse it. This should help with performance of Assistant Panel with long conversations. Release Notes: - Improved performance of assistant panel with large # of text.
This commit is contained in:
parent
30a677e257
commit
783cccf95d
1 changed files with 31 additions and 10 deletions
|
@ -783,11 +783,13 @@ impl<'a> BlockMapWriter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
|
blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
|
||||||
) -> Vec<CustomBlockId> {
|
) -> Vec<CustomBlockId> {
|
||||||
let mut ids = Vec::new();
|
let blocks = blocks.into_iter();
|
||||||
|
let mut ids = Vec::with_capacity(blocks.size_hint().1.unwrap_or(0));
|
||||||
let mut edits = Patch::default();
|
let mut edits = Patch::default();
|
||||||
let wrap_snapshot = &*self.0.wrap_snapshot.borrow();
|
let wrap_snapshot = &*self.0.wrap_snapshot.borrow();
|
||||||
let buffer = wrap_snapshot.buffer_snapshot();
|
let buffer = wrap_snapshot.buffer_snapshot();
|
||||||
|
|
||||||
|
let mut previous_wrap_row_range: Option<Range<u32>> = None;
|
||||||
for block in blocks {
|
for block in blocks {
|
||||||
let id = CustomBlockId(self.0.next_block_id.fetch_add(1, SeqCst));
|
let id = CustomBlockId(self.0.next_block_id.fetch_add(1, SeqCst));
|
||||||
ids.push(id);
|
ids.push(id);
|
||||||
|
@ -797,11 +799,18 @@ impl<'a> BlockMapWriter<'a> {
|
||||||
let wrap_row = wrap_snapshot
|
let wrap_row = wrap_snapshot
|
||||||
.make_wrap_point(Point::new(point.row, 0), Bias::Left)
|
.make_wrap_point(Point::new(point.row, 0), Bias::Left)
|
||||||
.row();
|
.row();
|
||||||
let start_row = wrap_snapshot.prev_row_boundary(WrapPoint::new(wrap_row, 0));
|
|
||||||
let end_row = wrap_snapshot
|
|
||||||
.next_row_boundary(WrapPoint::new(wrap_row, 0))
|
|
||||||
.unwrap_or(wrap_snapshot.max_point().row() + 1);
|
|
||||||
|
|
||||||
|
let (start_row, end_row) = {
|
||||||
|
previous_wrap_row_range.take_if(|range| !range.contains(&wrap_row));
|
||||||
|
let range = previous_wrap_row_range.get_or_insert_with(|| {
|
||||||
|
let start_row = wrap_snapshot.prev_row_boundary(WrapPoint::new(wrap_row, 0));
|
||||||
|
let end_row = wrap_snapshot
|
||||||
|
.next_row_boundary(WrapPoint::new(wrap_row, 0))
|
||||||
|
.unwrap_or(wrap_snapshot.max_point().row() + 1);
|
||||||
|
start_row..end_row
|
||||||
|
});
|
||||||
|
(range.start, range.end)
|
||||||
|
};
|
||||||
let block_ix = match self
|
let block_ix = match self
|
||||||
.0
|
.0
|
||||||
.custom_blocks
|
.custom_blocks
|
||||||
|
@ -881,6 +890,7 @@ impl<'a> BlockMapWriter<'a> {
|
||||||
let buffer = wrap_snapshot.buffer_snapshot();
|
let buffer = wrap_snapshot.buffer_snapshot();
|
||||||
let mut edits = Patch::default();
|
let mut edits = Patch::default();
|
||||||
let mut last_block_buffer_row = None;
|
let mut last_block_buffer_row = None;
|
||||||
|
let mut previous_wrap_row_range: Option<Range<u32>> = None;
|
||||||
self.0.custom_blocks.retain(|block| {
|
self.0.custom_blocks.retain(|block| {
|
||||||
if block_ids.contains(&block.id) {
|
if block_ids.contains(&block.id) {
|
||||||
let buffer_row = block.position.to_point(buffer).row;
|
let buffer_row = block.position.to_point(buffer).row;
|
||||||
|
@ -889,21 +899,32 @@ impl<'a> BlockMapWriter<'a> {
|
||||||
let wrap_row = wrap_snapshot
|
let wrap_row = wrap_snapshot
|
||||||
.make_wrap_point(Point::new(buffer_row, 0), Bias::Left)
|
.make_wrap_point(Point::new(buffer_row, 0), Bias::Left)
|
||||||
.row();
|
.row();
|
||||||
let start_row = wrap_snapshot.prev_row_boundary(WrapPoint::new(wrap_row, 0));
|
let (start_row, end_row) = {
|
||||||
let end_row = wrap_snapshot
|
previous_wrap_row_range.take_if(|range| !range.contains(&wrap_row));
|
||||||
.next_row_boundary(WrapPoint::new(wrap_row, 0))
|
let range = previous_wrap_row_range.get_or_insert_with(|| {
|
||||||
.unwrap_or(wrap_snapshot.max_point().row() + 1);
|
let start_row =
|
||||||
|
wrap_snapshot.prev_row_boundary(WrapPoint::new(wrap_row, 0));
|
||||||
|
let end_row = wrap_snapshot
|
||||||
|
.next_row_boundary(WrapPoint::new(wrap_row, 0))
|
||||||
|
.unwrap_or(wrap_snapshot.max_point().row() + 1);
|
||||||
|
start_row..end_row
|
||||||
|
});
|
||||||
|
(range.start, range.end)
|
||||||
|
};
|
||||||
|
|
||||||
edits.push(Edit {
|
edits.push(Edit {
|
||||||
old: start_row..end_row,
|
old: start_row..end_row,
|
||||||
new: start_row..end_row,
|
new: start_row..end_row,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
self.0.custom_blocks_by_id.remove(&block.id);
|
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
self.0
|
||||||
|
.custom_blocks_by_id
|
||||||
|
.retain(|id, _| !block_ids.contains(id));
|
||||||
self.0.sync(wrap_snapshot, edits);
|
self.0.sync(wrap_snapshot, edits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue