Performance Issue
Renacer tracing reveals excessive memory allocations during suggestion.
Evidence
$ renacer -c -- aprender-shell suggest "cargo "
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
73.18 0.008002 8 970 brk # ❌ 970 allocations!
2.26 0.000247 11 22 mmap
13.98 0.001529 169 9 read
...
970 brk syscalls for a single suggestion is excessive. Each brk is a heap expansion.
Impact
- ~8ms spent just on memory allocation
- Total syscall overhead: ~11ms per suggestion
- In the widget (called on every keystroke), this adds up
Analysis
The brk calls suggest:
- Many small allocations during model traversal
- Possible lack of pre-allocation for results
- String allocations for each n-gram lookup
Suggested Fixes
1. Pre-allocate result buffers
fn suggest(&self, prefix: &str, count: usize) -> Vec<Suggestion> {
let mut results = Vec::with_capacity(count); // Pre-allocate
// ...
}
2. Use arena allocator for hot path
use bumpalo::Bump;
fn suggest(&self, prefix: &str) -> Vec<Suggestion> {
let arena = Bump::new();
// Allocate intermediate strings in arena
// Only clone final results to heap
}
3. Cache model in memory-mapped file
Instead of deserializing on each call, use mmap:
let model = unsafe { memmap2::Mmap::map(&file)? };
4. Lazy model loading with static lifetime
static MODEL: OnceLock<Model> = OnceLock::new();
fn get_model() -> &'static Model {
MODEL.get_or_init(|| Model::load_default().unwrap())
}
Benchmarks Needed
- Baseline: current allocation count
- Target: <100 allocations per suggestion
- Measure with
renacer -c --stats-extended
Related
- Discovered via renacer integration testing
- Affects real-time suggestion latency
Performance Issue
Renacer tracing reveals excessive memory allocations during suggestion.
Evidence
970
brksyscalls for a single suggestion is excessive. Eachbrkis a heap expansion.Impact
Analysis
The
brkcalls suggest:Suggested Fixes
1. Pre-allocate result buffers
2. Use arena allocator for hot path
3. Cache model in memory-mapped file
Instead of deserializing on each call, use mmap:
4. Lazy model loading with static lifetime
Benchmarks Needed
renacer -c --stats-extendedRelated