Summary
The session list render loop allocates new padding strings on every frame via strings.Repeat, creating thousands of short-lived allocations per second in the TUI hot path.
Problem
In sessionlist.go (lines 614-625), the Render() method pads the viewport to full height:
// Pad to full height.
for len(lines) < s.height {
lines = append(lines, strings.Repeat(" ", s.width))
}
// ... after join + split safety net:
for len(all) < s.height {
all = append(all, strings.Repeat(" ", s.width))
}
Each strings.Repeat(" ", s.width) allocates a new string. With a typical terminal (200 columns, 50 rows), this creates up to 50+ allocations per frame. Bubble Tea can render at 60 FPS during interaction, producing ~3,000 allocations/sec from padding alone.
Recommended Fix
Cache the padding string and invalidate only when terminal width changes:
type SessionList struct {
// ...
cachedPad string
cachedPadWidth int
}
func (s *SessionList) pad() string {
if s.cachedPadWidth != s.width {
s.cachedPad = strings.Repeat(" ", s.width)
s.cachedPadWidth = s.width
}
return s.cachedPad
}
Then replace both call sites:
lines = append(lines, s.pad())
Impact
- Severity: Medium-High
- Affected operations: Every TUI frame render
- Expected improvement: Eliminates ~3,000 string allocations/sec during active interaction; reduces GC pressure
Summary
The session list render loop allocates new padding strings on every frame via strings.Repeat, creating thousands of short-lived allocations per second in the TUI hot path.
Problem
In sessionlist.go (lines 614-625), the
Render()method pads the viewport to full height:Each
strings.Repeat(" ", s.width)allocates a new string. With a typical terminal (200 columns, 50 rows), this creates up to 50+ allocations per frame. Bubble Tea can render at 60 FPS during interaction, producing ~3,000 allocations/sec from padding alone.Recommended Fix
Cache the padding string and invalidate only when terminal width changes:
Then replace both call sites:
Impact