Skip to content

perf(display): snapshot mirror — viewer gating, digest skip, health keepalive#404

Open
ChuckBuilds wants to merge 1 commit into
mainfrom
fix/snapshot-viewer-gating
Open

perf(display): snapshot mirror — viewer gating, digest skip, health keepalive#404
ChuckBuilds wants to merge 1 commit into
mainfrom
fix/snapshot-viewer-gating

Conversation

@ChuckBuilds

Copy link
Copy Markdown
Owner

Summary

PR 2 of the performance series. The display service PNG-encoded its frame to /tmp/led_matrix_preview.png at 5 fps, 24/7 — identical frames, no viewers, per-call imports and a chmod on every write.

  • Pure policy module (src/common/snapshot_policy.py, unit-tested off-Pi): full-rate writes only while a browser preview is actually watching; 30s idle cadence otherwise; unchanged frames are never re-encoded — the file mtime is touched every 20s instead, keeping the health check's snapshot-age liveness proxy (60s threshold in api_v3) green. Cross-referencing comments guard both constants.
  • Viewer detection: the web SSE display broadcaster (which only runs while browsers are subscribed) touches /tmp/led_matrix_preview_viewer each loop; the display service stats it at most once per second. On viewer arrival the write clock resets so the first frame lands within ~1s.
  • Hoisted the per-call pathlib/permission_utils imports; directory permissions ensured once, not per frame.

Honest measurement note

Pinned-content A/B on the devpi (192×48, on-demand-pinned modes, 45s samples): CPU-neutral — 69.8% vs 69.7% (static), 70.4% vs 70.5% (scroll). The PNG encodes this removes are cheap relative to the discovery that ~70% is a constant floor from the rgbmatrix driver's refresh thread (capped at the default 90Hz) in all scenarios — panel-driver tuning, not Python, owns that budget. The value of this PR is behavioral: near-zero snapshot I/O without viewers, no redundant encodes ever, health semantics preserved and documented, and the policy is now testable. Verified live on the devpi: writes gated correctly, keepalive holds the health check 'connected', preview page works.

10 unit tests on the policy (including a worst-case interleaving bound on mtime age).

🤖 Generated with Claude Code

https://claude.ai/code/session_01FqzC1nzTWL4kaqgMaQZFam

The display service PNG-encoded its frame to /tmp/led_matrix_preview.png
at 5 fps, 24/7 — identical frames, no viewers, per-call imports and a
chmod every write. On the devpi baseline the display service idles at
~92% CPU; this was one of its biggest fixed costs.

- New pure policy (src/common/snapshot_policy.py, unit-tested off-Pi):
  WRITE changed frames at full rate only while a viewer is watching,
  at a 30s idle cadence otherwise; NEVER re-encode unchanged frames —
  bump mtime (os.utime) every 20s instead, keeping the health check's
  snapshot-age liveness proxy (60s threshold in api_v3) green. Cross-
  referencing comments guard the two constants.
- Viewer detection: the web SSE display broadcaster (which only runs
  while browsers are subscribed) touches /tmp/led_matrix_preview_viewer
  each loop; the display service stats it at most 1/s. On viewer
  arrival the write clock resets so the first frame lands within ~1s.
- Hoisted the per-call pathlib/permission_utils imports; directory
  permissions ensured once instead of every frame.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FqzC1nzTWL4kaqgMaQZFam
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@ChuckBuilds, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 13 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 49380ceb-d6b9-4dab-99a7-aac52a74e07f

📥 Commits

Reviewing files that changed from the base of the PR and between 6edd80d and 62fbed3.

📒 Files selected for processing (4)
  • src/common/snapshot_policy.py
  • src/display_manager.py
  • test/test_snapshot_policy.py
  • web_interface/app.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/snapshot-viewer-gating

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 9 complexity · 0 duplication

Metric Results
Complexity 9
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant