perf: dirty-flag rendering + synchronized output (DEC PM 2026) - #19
Open
wasabeef wants to merge 1 commit into
Open
perf: dirty-flag rendering + synchronized output (DEC PM 2026)#19wasabeef wants to merge 1 commit into
wasabeef wants to merge 1 commit into
Conversation
Two independent rendering optimizations: ## Dirty-flag rendering (needs_render) Add `needs_render: bool` to `AppState` (default true). Background tasks and state-mutation methods set the flag; the main event loop skips `terminal.draw()` when neither user input nor a state change occurred. Eliminates the unconditional ~125 fps redraw when the app is idle: - `add_log()` / device-status helpers / `update_cached_device_details()` set the flag directly inside the existing mutation methods. - Background spawns in `api_levels`, `background`, `create_device`, `refresh` set `state.needs_render = true` (or call `mark_dirty()`) after direct field mutations that bypass the helper methods. - `add_notification()` / `dismiss_expired_notifications()` set the flag so notification appearance and auto-dismiss trigger renders. ## Synchronized Output (DEC PM 2026) Wrap every `terminal.draw()` call with `crossterm::queue!(BeginSynchronizedUpdate)` before and `crossterm::execute!(EndSynchronizedUpdate)` after. The terminal buffers all display writes between the two escape sequences (`\x1b[?2026h` / `\x1b[?2026l`) and paints them atomically, preventing partial-frame flicker on supporting terminals (iTerm2, kitty, WezTerm, Windows Terminal ...). Terminals that do not support the protocol silently ignore the sequences - no behaviour change on unsupported terminals. crossterm 0.29 exposes `BeginSynchronizedUpdate` / `EndSynchronizedUpdate` natively so no extra dependency is needed.
Code Metrics Report
Code coverage of files in pull request scope (50.5%)
Reported by octocov |
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
Inspired by Claude Code's NO_FLICKER mode investigation — emu already uses alt-screen rendering (the core of NO_FLICKER), but two lower-level optimizations were missing.
1. Dirty-flag rendering (
needs_render)Add
pub needs_render: booltoAppState(defaulttruefor initial paint).Before:
terminal.draw()was called unconditionally on every event-loop iteration — roughly 125 fps even when the screen was completely static.After: The main loop skips
terminal.draw()unless either:events_processed > 0(user pressed a key), orstate.needs_render == true(a background task updated visible state)Coverage across all background mutation paths:
state/logs.rsadd_log(),update_single_*_device_status()callself.needs_render = truestate/details.rsupdate_cached_device_details()state/mod.rsadd_notification(),dismiss_expired_notifications()(conditional)background.rsmark_dirty()refresh.rsmark_dirty()api_levels.rscreate_device.rs2. Synchronized Output (DEC PM 2026)
Wrap each
terminal.draw()with:The terminal receives
\x1b[?2026h, then all cell-diff writes from ratatui (in a single flush), then\x1b[?2026l. Supporting terminals (iTerm2, kitty, WezTerm, Windows Terminal, …) buffer everything between the two sequences and paint atomically — no partial-frame flicker.crossterm 0.29 already exposes
BeginSynchronizedUpdate/EndSynchronizedUpdatenatively, so no new dependency is required. Terminals that do not support the protocol silently ignore the sequences.Test plan
cargo clippy --all-targets --all-features -- -D warnings— cleanRUST_TEST_THREADS=1 cargo test --bins --tests --features test-utils— 790 tests pass (pre-push hook verified)error_recovery_test::test_resource_exhaustion_recovery) confirmed pre-existing env-var race; passes in isolation and on main