Repository navigation
perf(ui): render only the visible page of address-tab rows - #93
Merged
Merged
Conversation
Every frame built a ListItem for every row of the active address tab, with several linear registry lookups per row. On a contract with ~52k cached calls and ~760 user labels a frame cost ~170 ms, so each keystroke (and each pasted character) paid it. Add ListWindow, which mirrors ratatui's List offset rule for single-line rows, and build rows only for that window in the Txs, Calls, MetaTxs and Events tabs. Gap rows keep their rendered positions via a shared rendered_row() mapping that the selection code now uses too. Bench (release, 220x60 TestBackend, 52k rows / 759 labels): Calls tab 170 ms -> 0.7 ms per frame; Txs tab 1.1 ms; flat in row count. Follow-ups: #90 (O(1) registry lookups), #91 (input priority in the main loop), #92 (per-WS-event O(n) work). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 13, 2026
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.
Problem
Every frame built a
ListItemfor every row of the active address tab (Txs, Calls, MetaTxs, Events), each with several linear registry lookups, ~10format!allocations and aUtc::now(). Ratatui then painted ~55 of them.Since
run_loopredraws after every terminal event, each keystroke paid a full frame, and a pasted address arrives as one key event per character. On a contract with ~52k cached calls and ~760 user labels a frame cost ~170 ms: pressing/lagged, and a 66-char paste took ~11 s and appeared character by character. The main thread had burned ~117 CPU-seconds in 9 minutes while all tokio workers together used ~7.Change
ListWindow(src/ui/widgets/list_window.rs) mirrors ratatui'sListoffset rule for single-line rows (no scroll padding): keep the stored offset unless the selection leaves the page, clamp to the list. Callers build rows forwindow.range()only;render()draws with the selection rebased to the window and writes the absolute offset/selection back into the persistentListState, sotxs_render_state.offset()consumers (enrichment window) keep working.src/ui/views/address_info.rsrender through it. Row bodies moved intotx_row/call_row/meta_tx_rowunchanged; list chrome deduped intolist_block/highlighted_list.rendered_row()(src/app/views/address_info.rs), whichapply_rendered/apply_call_renderednow use instead of a private inverse mapping. New*_rendered_selected_with(&gaps)variants avoid recomputing gap positions twice per frame.Bench
Release profile, 220x60
TestBackend, realui::draw, synthetic rows (temporary example, not committed):Frame cost is now flat in list size. Verified interactively on a large-history contract: search and paste are immediate.
Tests
ListWindow::new(empty, clamped offset, selection above/below page, tail page) and forrendered_row(interleaving, round-trip withtx_pos_to_rendered).cargo test,cargo clippy --all-targets(no new warnings),cargo build --release.Follow-ups
select!, coalesce buffered key events.🤖 Generated with Claude Code