gpui: Remove intermediate allocations when reconstructing text from a `TextLayout` (#45037)
tidely
created 1 week ago
Closes #ISSUE
Remove some intermediate allocations when reconstructing text or wrapped
text from a `TextLayout`. Currently creates a intermediate `Vec<String>`
which gets joined, when you could join an `impl Iterator<Item = &str>`
Release Notes:
- N/A *or* Added/Fixed/Improved ...
Change summary
crates/gpui/src/elements/text.rs | 18 +++++++++++-------
crates/markdown/src/markdown.rs | 9 ++++++---
2 files changed, 17 insertions(+), 10 deletions(-)
Detailed changes
@@ -6,6 +6,7 @@ use crate::{
register_tooltip_mouse_handlers, set_tooltip_on_window,
};
use anyhow::Context as _;
+use itertools::Itertools;
use smallvec::SmallVec;
use std::{
borrow::Cow,
@@ -597,14 +598,14 @@ impl TextLayout {
.unwrap()
.lines
.iter()
- .map(|s| s.text.to_string())
- .collect::<Vec<_>>()
+ .map(|s| &s.text)
.join("\n")
}
/// The text for this layout (with soft-wraps as newlines)
pub fn wrapped_text(&self) -> String {
- let mut lines = Vec::new();
+ let mut accumulator = String::new();
+
for wrapped in self.0.borrow().as_ref().unwrap().lines.iter() {
let mut seen = 0;
for boundary in wrapped.layout.wrap_boundaries.iter() {
@@ -612,13 +613,16 @@ impl TextLayout {
[boundary.glyph_ix]
.index;
- lines.push(wrapped.text[seen..index].to_string());
+ accumulator.push_str(&wrapped.text[seen..index]);
+ accumulator.push('\n');
seen = index;
}
- lines.push(wrapped.text[seen..].to_string());
+ accumulator.push_str(&wrapped.text[seen..]);
+ accumulator.push('\n');
}
-
- lines.join("\n")
+ // Remove trailing newline
+ accumulator.pop();
+ accumulator
}
}
@@ -1919,7 +1919,7 @@ impl RenderedText {
}
fn text_for_range(&self, range: Range<usize>) -> String {
- let mut ret = vec![];
+ let mut accumulator = String::new();
for line in self.lines.iter() {
if range.start > line.source_end {
@@ -1944,9 +1944,12 @@ impl RenderedText {
}
.min(text.len());
- ret.push(text[start..end].to_string());
+ accumulator.push_str(&text[start..end]);
+ accumulator.push('\n');
}
- ret.join("\n")
+ // Remove trailing newline
+ accumulator.pop();
+ accumulator
}
fn link_for_position(&self, position: Point<Pixels>) -> Option<&RenderedLink> {