perf: precompute session-scoped style set to eliminate per-frame allocations - #97
Merged
Conversation
… allocations
The theme is fixed at startup and never changes, yet every frame built
~300-400 fresh lipgloss.Style structs via styleWithFg / lipgloss.NewStyle()
calls scattered across the hot render paths.
Added a themeStyles struct (tui/styles.go) with 26 pre-built Style fields,
populated once in NewModel via newThemeStyles(theme) and stored as m.styles.
Threaded through internal structs (treePaneInput, splitTreeInput,
viewerParams) so the hot per-row renderers read a field instead of
allocating.
Replaced all static styleWithFg / lipgloss.NewStyle() calls in:
- tui/model.go — renderHeader, renderStatusBar, renderViewerStatusBar,
viewLoading, viewError, separator line
- tui/filetree.go — renderTreeHeader, renderFilterBar, renderSplitDivider,
formatFileNodeLine, renderNameWithHighlight
- tui/layers.go — renderCommandBar, highlightInstruction, formatLayerLine,
renderSizeColumn
- tui/fileview.go — renderViewerLine, renderViewerSearchBar, overlayCursor,
gutter, truncation/binary/empty notices
Dynamic styles (per-row diff color, delta color, selected-row bg,
search-current highlight) remain inline as their color varies per call.
Updated all test call sites to pass themeStyles{} (zero value is correct
for structural tests that check content not color).
The sb.WriteString(pad) line in renderTreeBody's empty-tree placeholder was indented one tab short of its sibling statement, a whitespace glitch introduced alongside the style-cache change. Pure formatting; no behaviour change.
The botBody treePaneInput literal in renderSplitFileTree was missing styles: in.styles, so the Cumulative pane in aggregated split mode rendered with a zero-value themeStyles — no colors, no diff highlighting, no selection background, no search styling. topBody was correctly threaded; this brings botBody in line.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
lipgloss.Stylevalues are now built once at startup into athemeStylesstruct (tui/styles.go) and reused for every frame. The theme is immutable for the session, so the ~300–400 per-frame style allocations that were rebuilding identical structs on everyView()call are eliminated.m.stylesand threaded through the internal render structs (treePaneInput,splitTreeInput,viewerParams) so the hot per-row renderers read a field rather than callinglipgloss.NewStyle().themeStyles{}(zero value is correct for structural tests that check rendered content, not color).Changes
tui/styles.go— newthemeStylesstruct (26 fields) andnewThemeStyles(Theme)constructortui/model.go—styles themeStylesfield on model; static calls replaced inrenderHeader,renderStatusBar,renderViewerStatusBar,viewLoading,viewError, separator linetui/filetree.go—treePaneInput/splitTreeInputcarrystyles; static calls replaced inrenderTreeHeader,renderFilterBar,renderSplitDivider,formatFileNodeLine,renderNameWithHighlighttui/layers.go— static calls replaced inrenderCommandBar,highlightInstruction,formatLayerLine,renderSizeColumntui/fileview.go—viewerParamscarriesstyles; static calls replaced inrenderViewerLine,renderViewerSearchBar,overlayCursor, gutter, and binary/empty/truncation noticesTest plan
go build ./...andgo vet ./...cleango test ./...)