From adaf2bf2828215c8c3525703a6850ea4b0ec61fd Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 08:26:29 +0000 Subject: [PATCH] refactor: optimize string capacity allocation in lsp range_formatting Co-authored-by: Tcode-Motion <188012755+Tcode-Motion@users.noreply.github.com> --- .jules/bolt.md | 3 +++ tools/lsp/src/lib.rs | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 5034e016..110a0b82 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -20,3 +20,6 @@ ## 2024-08-01 - Bytecode Disassembler String Allocation Optimization **Learning:** Formatting directly into a string buffer inside a tight loop with `write!(buffer, ...)` avoids unnecessary string heap allocations compared to `buffer.push_str(&format!(...))`. **Action:** Always prefer formatting directly into the target String buffer when concatenating strings in loops in performance-sensitive paths like debuggers or disassemblers. +## 2024-05-19 - [Optimize string concatenation in LSP range_formatting] +**Learning:** Temporary files created for testing performance locally, especially compiled executable binaries, will cause CI pollution and code review failure if not deleted before submitting a patch. String concatenation in a loop over slices can be highly optimized by pre-calculating capacity. +**Action:** Always delete scratch benchmark files (e.g. `rm -f test_perf*`) immediately after use and before requesting code review. Always use `String::with_capacity` when iterating over slices to avoid intermediate reallocation overhead. diff --git a/tools/lsp/src/lib.rs b/tools/lsp/src/lib.rs index 9e8845d5..ce2cc4a5 100644 --- a/tools/lsp/src/lib.rs +++ b/tools/lsp/src/lib.rs @@ -1291,11 +1291,18 @@ impl LanguageServer for Backend { let start = range.start.line as usize; let end = (range.end.line as usize).min(lines.len() - 1); - let mut selection = String::new(); - for i in start..=end { - selection.push_str(lines[i]); - selection.push('\n'); - } + let selection = if start <= end { + let slice = &lines[start..=end]; + let capacity: usize = slice.iter().map(|l| l.len() + 1).sum(); + let mut s = String::with_capacity(capacity); + for line in slice { + s.push_str(line); + s.push('\n'); + } + s + } else { + String::new() + }; let formatted = self.format_source(&selection); Ok(Some(vec![TextEdit {