Let the render loop park when the app is idle
- Linguagem predominante
- Rust
- Estrelas
- 71
- Forks
- 5
- Merge médio
- 4h 2min
- PRs com merge (30d)
- 31
Descrição
Follow-up from #509 (tears 0.11 migration). Not a regression that PR introduced — it is an opportunity the frame-rate removal opened and that PR deliberately left out of scope.
## Background
Until tears 0.11 the runtime rendered on a configured period (nostui's `--frame-rate`, default 16/s). In 0.11 that period is gone: the loop renders when an update pass leaves the view dirty, and **parks when it has no work**.
nostui does not benefit from the parking half yet, because nothing in the update path ever declines a redraw.
## Parts
Ordering matters between two of these: **(a) must land before (c)**, or the measurement is taken against a baseline that includes renders already known to be waste.
- [x] **(a) Stop redrawing for the two notification arms that change nothing.** Independent, a few lines, no measurement needed — see the comment below. `ClientNotification::Event` and a `Message` carrying anything other than `RelayMessage::Event` only log, and the pool emits both notifications for each newly-seen event, so the ignored one currently forces a full render for nothing.
- [x] **(b) Stop redrawing on ticks that changed no displayed value** (part 1 below). Ships together with an update to the `Removed: --frame-rate` entry in `docs/MIGRATION_GUIDE.md`, which currently tells users that lowering `--tick-rate` is the nearest replacement for the old throttle — this is the change that removes that property.
- [ ] **(c) Measure `pulled` on the `tears::runtime::load` batch event** under both workloads in part 2 below. After (a).
- [ ] **(d) Decide part 2 from that measurement and record the decision**, even if the decision is "no change needed".
## What to do
**1. Ticks should not redraw by themselves.**
`SystemMsg::Tick` reaches `AppState::record_tick`, which bumps the FPS counter and returns `Command::none()` — a redrawing command. So a completely idle nostui still runs a pass and re-renders the whole timeline 16 times a second in order to refresh a counter whose displayed value only changes once a second. The park never engages.
`Fps::update` already knows when the displayed value changed (it recomputes `app_fps` only when at least a second has elapsed). Returning `Command::none().without_redraw()` on the ticks that changed nothing, and a redrawing command on the tick that did, would take idle redraws from 16/s to 1/s.
**2. Decide what to do about event-driven redraws.**
Every `AppMsg::Nostr(..)` dispatch marks the view dirty, and there is no longer a ceiling above it, so on a busy home feed redraw frequency tracks relay throughput.
This is *probably* fine and may already be an improvement: tears batches up to 1024 inputs into one pass, so a burst coalesces into a single render, and a quiet feed now costs fewer renders than the old unconditional 16/s. But it is untested. Worth measuring `pulled` on the `tears::runtime::load` batch event under a real feed before deciding whether anything is needed here.
If it does turn out to need bounding, the shape tears recommends is to throttle in the state that drives the view — coalesce notification updates and let a periodic redraw flush them — not to reintroduce a frame rate.
## Why it was not done in #509
It changes when the FPS widget refreshes, which is a user-visible behaviour change unrelated to the dependency bump, and part 2 wants measurement rather than a guess. Keeping #509 to the migration keeps the bisect boundary clean.
## Acceptance
- An idle nostui (no relay traffic, no input) renders about once per second rather than 16 times.
- The FPS display still updates once per second and still reads as ticks per second.
- A decision is recorded for part 2, backed by a measurement, even if the decision is "no change needed".
Guia de contribuição
Avaliação
Esta issue ainda não foi avaliada.