perf: redraw on change, cache catalogue reads, keep album art alive in tmux - #3
Merged
Merged
Conversation
…n tmux Three things that turned up while chasing a jerky scroll: the UI redrew on a fixed schedule no matter what changed, every artist page went back to the network, and inline album art vanished the moment you switched tmux windows. A sample of the running process spent 419 of 6066 samples on the main thread — all of it redrawing frames identical to the last one. Redraws - Draw when something changed rather than on a timer: input redraws within one 16ms refresh, animation runs at 30fps, an untouched screen at 2fps instead of 60. Holding an arrow key waited up to 100ms per step before, which is what made scrolling look torn - Count the visualizer as animating only while Now Playing is on screen - Move the queue refresh and state save off the frame counter onto a timer; at 60fps they were firing every four seconds, burning API quota and disk writes Cache - Cache catalogue reads and album art under ~/.cache/myx/api, and serve a stale entry when a request fails — a spent development-mode quota is exactly when an artist page would otherwise come up empty - Never cache a failed cover request: image entries never expire, so an error body would mean a permanently broken cover - Write through a temp file and rename, and sweep entries older than 30 days Album art - Draw sixel, unwrapped, where tmux reports sixel support. It is the only image protocol tmux parses and repaints from its own buffer; kitty and iTerm2 ride through as passthrough, untracked, and are gone on the next repaint - Give WezTerm and Warp iTerm2 images. Both answer the kitty query but neither places unicode placeholders, which is how ratatui-image draws kitty, so the cover came out as a see-through hole - Re-send the art on a view switch, and clear the box when there is no cover, so another view can't show through cells the image widget marks as skipped Config - Write ~/.config/myx/config.toml on first run with every key commented out - Add a protocol key (kitty, iterm2, sixel, halfblocks) for when detection picks wrong; MYX_PROTOCOL still overrides it 54 tests, plus an ignored encode_cost benchmark: kitty 1.5ms, iTerm2 1.9ms, halfblocks 2.6ms, sixel 8.7ms per re-encode.
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.
Chasing a torn-looking scroll turned up three separate things.
Redraws ran on a timer, not on changes. A
sampleof the running process spent 419 of 6066 samples on the main thread, almost all of it drawing frames identical to the previous one. Holding an arrow key waited up to 100ms per step, because a keypress didn't force a frame — only the mouse and resize did. Now input redraws within one 16ms refresh, animation runs at 30fps, and an untouched screen at 2fps. The visualizer only counts as animating while Now Playing is on screen, and the queue refresh + state save moved off the frame counter onto a timer — at 60fps they were firing every four seconds.Every artist page went back to the network. Catalogue reads and album art are cached under
~/.cache/myx/api, and a stale entry is served when a request fails — a spent development-mode quota is exactly the moment an artist page would otherwise come up empty. Failed cover requests are never cached (image entries don't expire, so an error body would mean a permanently broken cover), writes go through temp + rename, and entries older than 30 days are swept once per run.Album art vanished on a tmux window switch. Not a redraw problem: kitty and iTerm2 images travel as tmux passthrough, which tmux doesn't parse or store, so when it repaints a pane from its own buffer the image was never there. Sixel is the one protocol tmux keeps and repaints itself, so where tmux reports sixel support that's what gets drawn — unwrapped, since
ratatui-image's passthrough wrapper is what would defeat it. WezTerm and Warp get iTerm2 instead of kitty: both answer the kitty query but place no unicode placeholders, which is how kitty is drawn here, so the cover came out as a see-through hole.Also:
~/.config/myx/config.tomlis written on first run with every key commented out, plus aprotocolkey for when detection picks wrong.54 tests pass, clippy and fmt are clean. An ignored
encode_costbenchmark records what a cover re-encode costs: kitty 1.5ms, iTerm2 1.9ms, halfblocks 2.6ms, sixel 8.7ms.