Skip to content

perf(tui): cache padding string in session list render loop #62

@jongio

Description

@jongio

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    automatedCreated by automationperfPerformance improvements

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions