editor: Use less memory when replacing literal strings (#46092)
Marco Mihai Condrache
created
Found while profiling #38927
When the query is not a regex, the same replacement can be applied to
all matches. Previously, `replacement_for` allocated a new String on
every call, while `replacement` returns a reference.
Release Notes:
- N/A
---------
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
@@ -1682,19 +1682,27 @@ impl SearchableItem for Editor {
let text = text.snapshot(cx);
let mut edits = vec![];
- for m in matches {- let text = text.text_for_range(m.clone()).collect::<Vec<_>>();-- let text: Cow<_> = if text.len() == 1 {- text.first().cloned().unwrap().into()- } else {- let joined_chunks = text.join("");- joined_chunks.into()- };
+ // A regex might have replacement variables so we cannot apply
+ // the same replacement to all matches
+ if query.is_regex() {
+ edits = matches
+ .filter_map(|m| {
+ let text = text.text_for_range(m.clone()).collect::<Vec<_>>();
+
+ let text: Cow<_> = if text.len() == 1 {
+ text.first().cloned().unwrap().into()
+ } else {
+ let joined_chunks = text.join("");
+ joined_chunks.into()
+ };
- if let Some(replacement) = query.replacement_for(&text) {- edits.push((m.clone(), Arc::from(&*replacement)));- }
+ query
+ .replacement_for(&text)
+ .map(|replacement| (m.clone(), Arc::from(&*replacement)))
+ })
+ .collect();
+ } else if let Some(replacement) = query.replacement().map(Arc::<str>::from) {
+ edits = matches.map(|m| (m.clone(), replacement.clone())).collect();
}
if !edits.is_empty() {