mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-10 09:06:36 +00:00
fix(perf): recorder review fixes -- period adoption, timed frames, snapshot copy, watchdog stop
From review (CodeRabbit): - The first refresh period is adopted only once two windows in a row agree. One loaded startup window, most frames a refresh late, used to fix a period twice the real one for the life of the process. - totals.timed_frames counts the frames judged against a known period, and frame_soak rates late and early frames over it. Before, frames seen before any period was known counted as on time, so a short run could PASS having judged nothing; now it has no verdict. - snapshot() copies totals. render_bench kept the snapshot object and differenced it against a later one sharing the same live dict, so every graded run reported zero frames. - held_refresh_hz uses the p50 bucket's midpoint, not its upper edge (a 1-2% low bias, the size of the idle-vs-held gap it exists to show). - StallWatchdog.stop() and FrameTimingRecorder.close(); DisplayManager's cleanup() calls it, so the watchdog no longer outlives its manager. - A stall that outlasts the 2s scroll-state expiry still gets its end reported (tracking is dropped only past GAP_SECONDS). - test: EMULATOR through monkeypatch; docs: the 1s resume rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -334,7 +334,7 @@ service's user.
|
||||
| line | what it tells you |
|
||||
|---|---|
|
||||
| **Late frames** | Frames presented one or more refreshes after they were due: the panel showed the previous frame again, a visible hitch. **The pass/fail number**, 0.1% by default (`--max-late-pct`). Only intervals between two scrolling frames count, and a frame held for `frame_hold` refreshes is due `frame_hold` refreshes after the last. |
|
||||
| **Freezes** | Gaps of 250 ms or more inside a scroll: recomposes, plugin handovers, blocking calls on the render thread. Reported but not failed on, because some are handovers between plugins rather than faults. A gap still counts when the display's scroll state went missing across it (it expires after 2 s, and plugins clear it from their own `display()`), as long as the scroll carries on straight after. |
|
||||
| **Freezes** | Gaps of 250 ms or more inside a scroll: recomposes, plugin handovers, blocking calls on the render thread. Reported but not failed on, because some are handovers between plugins rather than faults. A gap still counts when the display's scroll state went missing for one frame across it, as long as scrolling resumes within 1 s: both of that frame's intervals count. Two static frames in a row end the scroll. (The state expires after 2 s without scroll activity, and plugins can clear it from their own `display()`.) The late and early rates are over frames judged against a known refresh period, which the recorder adopts once two windows in a row agree on it. |
|
||||
| **blit** | Copying the frame into the matrix canvas (`SetImage`). It grows with width × height × `pwm_bits`: ~5.5 ms at 512×64 with 8 bits on a Pi 4. It is the biggest fixed cost, and it sets the refresh rates a rig can hold one pixel per refresh at. |
|
||||
| **wait** | Time blocked in `SwapOnVSync`, i.e. the slack left in each refresh. A p50 near zero means the rig has no headroom and anything extra lands a frame late. |
|
||||
| **work** | Everything else between two frames: drawing, scrolling, and waiting for the GIL. A wide gap between its p50 and p99 is another thread getting in the way. |
|
||||
|
||||
Reference in New Issue
Block a user