⚡ Bolt: Remove intermediate allocations when joining strings#598
⚡ Bolt: Remove intermediate allocations when joining strings#598madmax983 wants to merge 1 commit into
Conversation
Replaced `.collect::<Vec<_>>().join(...)` with `fold` across the codebase to pre-allocate capacity and avoid intermediate vectors. Also applied minor clippy refactors. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
There was a problem hiding this comment.
Code Review
This pull request optimizes string joining operations across several files (calibrate.rs, swebench.rs, and skills.rs) by replacing vector collection and joining with inline fold operations to avoid intermediate allocations. It also simplifies a socket read loop, improves error reporting in test timeouts, and refactors a split operation. The review feedback suggests replacing the complex inline fold operations with more readable and idiomatic iterator loops that preallocate exact capacities, avoiding branching and unnecessary reallocations.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
|
||
| fn sorted_join(values: BTreeSet<&str>) -> String { | ||
| values.into_iter().collect::<Vec<_>>().join(",") | ||
| values.iter().enumerate().fold(String::with_capacity(values.iter().map(|s| s.len() + 1).sum()), |mut acc, (i, s)| { if i > 0 { acc.push(','); } acc.push_str(s); acc }) |
There was a problem hiding this comment.
The inline fold with enumerate is hard to read and introduces a conditional check on every iteration. We can simplify this by precalculating the exact capacity and using a clean iterator pattern with next() and a simple loop. This is more idiomatic, highly readable, and avoids branching inside the loop.
let total_len: usize = values.iter().map(|s| s.len()).sum();
let cap = total_len + values.len().saturating_sub(1);
let mut iter = values.into_iter();
let Some(first) = iter.next() else {
return String::new();
};
let mut acc = String::with_capacity(cap);
acc.push_str(first);
for s in iter {
acc.push(',');
acc.push_str(s);
}
acc| return Err(Error::Config(crate::error::ConfigError::Invalid(format!( | ||
| "--instance-ids references unknown id(s): {}", | ||
| unknown.into_iter().collect::<Vec<_>>().join(", ") | ||
| unknown.iter().enumerate().fold(String::with_capacity(unknown.iter().map(|s| s.len() + 2).sum()), |mut acc, (i, s)| { if i > 0 { acc.push_str(", "); } acc.push_str(s); acc }) | ||
| )))); |
There was a problem hiding this comment.
The inline fold here is complex and hard to read. Since this is an error path, we can write a clean, explicit string builder block that preallocates the exact capacity and joins the strings using a simple loop. This significantly improves readability and maintainability.
let total_len: usize = unknown.iter().map(|s| s.len()).sum();
let cap = total_len + unknown.len().saturating_sub(1) * 2;
let mut iter = unknown.into_iter();
let mut joined = String::with_capacity(cap);
if let Some(first) = iter.next() {
joined.push_str(first);
for s in iter {
joined.push_str(", ");
joined.push_str(s);
}
}
return Err(Error::Config(crate::error::ConfigError::Invalid(format!(
"--instance-ids references unknown id(s): {joined}"
))));| } | ||
| } | ||
| out.split_whitespace().collect::<Vec<_>>().join(" ") | ||
| out.split_whitespace().enumerate().fold(String::new(), |mut acc, (i, s)| { if i > 0 { acc.push(' '); } acc.push_str(s); acc }) |
There was a problem hiding this comment.
Using fold(String::new(), ...) without preallocating causes multiple reallocations as the string grows. Since we already have out, we can preallocate the exact upper bound capacity using out.len() and join the words using a clean iterator loop. This is more performant and much easier to read.
let mut iter = out.split_whitespace();
let Some(first) = iter.next() else {
return String::new();
};
let mut acc = String::with_capacity(out.len());
acc.push_str(first);
for s in iter {
acc.push(' ');
acc.push_str(s);
}
acc
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## trunk #598 +/- ##
==========================================
- Coverage 85.19% 85.19% -0.01%
==========================================
Files 114 114
Lines 65408 65404 -4
==========================================
- Hits 55725 55720 -5
- Misses 9683 9684 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
💡 What: Replaced
.collect::<Vec<_>>().join(...)with.fold(...)along withString::with_capacityto build strings directly. Additionally resolved awhile_let_looplint andmap_unwrap_orlint in unrelated files.🎯 Why:
.collect::<Vec<_>>().join(...)allocates an intermediate vector before allocating the joined string, taking extra CPU cycles and memory. Doing it manually with.foldskips the intermediate vector entirely.📊 Impact: Reduces heap allocs by 1 vector allocation for each call.
🔬 Measurement: Verified the code compiles, works correctly, and passes all tests without regressions via
cargo checkandcargo test.PR created automatically by Jules for task 15264098696242478243 started by @madmax983