Skip to content

Enhance performance with caching and batch operations#4011

Open
uozalp wants to merge 9 commits into
derailed:masterfrom
uozalp:refresh-performance
Open

Enhance performance with caching and batch operations#4011
uozalp wants to merge 9 commits into
derailed:masterfrom
uozalp:refresh-performance

Conversation

@uozalp
Copy link
Copy Markdown
Contributor

@uozalp uozalp commented May 24, 2026

Skip UI rebuild when data hasn't changed (internal/model/table.go)

TableData.Diff() existed but was never actually used in the refresh path.
Every 2 seconds the full pipeline ran (clone, filter, sort, reindex, rebuild
all cells) even when nothing in the cluster had changed. Now we keep a
previous snapshot and only fire TableDataChanged when Diff returns true.
On idle clusters this skips ~30 unnecessary full rebuilds per minute.

Batch delete with single reindex (internal/model1/row_event.go, internal/model1/table_data.go)

TableData.Delete() was calling RowEvents.Delete() in a loop, and each
call did a full reindex() of the index map. This was O(k*n) for k
deletions from n rows. Added DeleteBatch() that collects victims, filters
in one pass, and reindexes once. Benchmarked at 21x faster (1K rows)
to 82x faster (5K rows).

Cache resource.MustParse in capacity sort (internal/model1/helpers.go)

capacityToNumber() was calling resource.MustParse on every sort
comparison, roughly 2nlog(n) times per sort. Now parsed values are cached
in a map. Only unique capacity strings need actual parsing. About 3.4x
faster
per comparison.

Avoid extra clone in initSelectedColumn (internal/ui/table.go)

initSelectedColumn() called GetFilteredData() which did another
Peek() (full deep clone) even though the caller already had the data.
Added initSelectedColumnWith(data) that accepts already-available data
and updated doUpdate() to use it.

Load plugins/hotkeys from disk once per view (internal/view/browser.go)

refreshActions() was calling pluginActions() and hotKeyActions() on
every refresh cycle (every 2s). Both read config files from disk. This
blocked the UI goroutine and was particularly bad on slow filesystems
(NFS, network mounts). Now they load once when the browser starts and
the cached actions are reused for subsequent refreshes.

Column navigation without full table rebuild (internal/ui/table.go)

moveSelectedColumn() (Shift+Left/Right) was calling Refresh() which
rebuilt the entire table. Added refreshHeaders() that only updates the
header row cells. Goes from O(n*cols) to O(cols).

@uozalp uozalp marked this pull request as ready for review May 24, 2026 12:11
uozalp and others added 8 commits May 25, 2026 21:14
…erailed#3987)

FetchPodsMetrics and FetchNodesMetrics use empty ListOptions which
requests the entire metrics dataset in one shot. On clusters with
10k+ pods this hits the API server's max-request-bytes limit.

Switch to Limit/Continue chunked listing with pre-allocated Items
slices. Same data, same cache, bounded API calls.
…erailed#3986)

Extract a shared parallelRender helper that fans work across
NumCPU batch workers. Both Hydrate and GenericHydrate now delegate
to it, eliminating duplicated concurrency logic.

At 50k pods on a 10-core machine:
  Before: 216ms (50k goroutines + semaphore)
  After:    4ms (10 goroutines, no channels)

Also pre-sizes sortLabels slices and removes dead poolSize constant.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants