Skip to content

fix: reduce CPU usage, fix Vegas refresh, throttle high-FPS ticks#304

Merged
ChuckBuilds merged 3 commits intomainfrom
fix/cpu-usage-and-scroll-issues
Apr 2, 2026
Merged

fix: reduce CPU usage, fix Vegas refresh, throttle high-FPS ticks#304
ChuckBuilds merged 3 commits intomainfrom
fix/cpu-usage-and-scroll-issues

Conversation

@ChuckBuilds
Copy link
Copy Markdown
Owner

@ChuckBuilds ChuckBuilds commented Apr 2, 2026

Summary

  • Web UI Info CPU fix: Plugin was causing 90%+ CPU on RPi4. Socket-based IP detection tried first (zero subprocess), AP mode cached with 60s TTL, IP refresh interval reduced from 30s to 5m, display image cached between renders, font loaded once at init
  • Vegas mid-cycle refresh: hot_swap_content() now saves/restores scroll position during mid-cycle recomposition so the display updates without jumping back to position 0
  • High-FPS tick throttle: _tick_plugin_updates() was called 125x/sec in the scrolling loop with no benefit — now throttled to 1x/sec via _tick_plugin_updates_throttled()

Test plan

  • Run with only web-ui-info enabled, verify CPU drops from ~90% to under 15% on RPi4
  • Enable Vegas mode with 2+ plugins, trigger a data update mid-scroll, verify display refreshes without scroll position reset
  • Enable a scrolling plugin (stocks, news, etc.) and verify plugin updates still occur during high-FPS display

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Performance Improvements

    • IP polling reduced (30s → 5min) and AP-mode detection cached (60s)
    • Display rendering and font loading cached to avoid repeated work
    • Plugin update calls throttled during high‑FPS rendering
  • Bug Fixes

    • Display now refreshes when the device IP changes to ensure accurate info
    • Scroll position preserved during dynamic content swaps to prevent jumps

…-FPS plugin ticks

Web UI Info plugin was causing 90%+ CPU on RPi4 due to frequent subprocess
calls and re-rendering. Fixed by: trying socket-based IP detection first
(zero subprocess overhead), caching AP mode checks with 60s TTL, reducing
IP refresh from 30s to 5m, caching rendered display images, and loading
fonts once at init.

Vegas mode was not updating the display mid-cycle because hot_swap_content()
reset the scroll position to 0 on every recomposition. Now saves and
restores scroll position for mid-cycle updates.

High-FPS display loop was calling _tick_plugin_updates() 125x/sec with no
benefit. Added throttled wrapper that limits to 1 call/sec.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f2c585d4-08fd-42b3-9509-e0be0627e47c

📥 Commits

Reviewing files that changed from the base of the PR and between 220eaed and 8d5ade4.

📒 Files selected for processing (1)
  • src/vegas_mode/render_pipeline.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/vegas_mode/render_pipeline.py

📝 Walkthrough

Walkthrough

Reduced IP probe frequency and added short AP-mode caching in the WebUI plugin; display rendering now reuses a cached font and cached image; high‑FPS display loop throttles plugin-update ticks; Vegas pipeline preserves scroll state when hot-swapping mid-cycle.

Changes

Cohort / File(s) Summary
Web-UI Plugin (display & IP logic)
plugin-repos/web-ui-info/manager.py
IP refresh interval changed 30s → 5min; added 60s TTL cache for AP-mode detection; _get_local_ip() now prefers UDP socket-based discovery with interface and hostname fallbacks retained; added _load_font() and cached self._font_small; display() caches rendered image and reuses it when rotation/force_clear/IP unchanged; update() marks display dirty when device_ip changes.
DisplayController (throttled plugin ticks)
src/display_controller.py
Added self._last_plugin_tick_time and _tick_plugin_updates_throttled(min_interval: float); high‑FPS dynamic loop now calls throttled ticks (min_interval ~1.0) instead of direct _tick_plugin_updates(); other paths unchanged.
Vegas render pipeline (hot-swap state preservation)
src/vegas_mode/render_pipeline.py
hot_swap_content() snapshots and restores scroll helper state when hot-swap occurs mid-cycle to maintain scroll continuity; logging updated to indicate mid-cycle restore.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the three main changes: CPU usage reduction, Vegas refresh fix, and high-FPS tick throttling, matching the changeset across all three modified files.
Docstring Coverage ✅ Passed Docstring coverage is 92.31% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cpu-usage-and-scroll-issues

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
plugin-repos/web-ui-info/manager.py (1)

83-85: Use specific exceptions in new fallback paths.

The new broad catches at Line 83 and Line 155 can hide concrete runtime issues and reduce debuggability.

♻️ Proposed refactor
-        except Exception as e:
+        except (OSError, ValueError) as e:
             self.logger.debug(f"Could not load custom font: {e}, using default")
             return ImageFont.load_default()
-            except Exception:
+            except OSError:
                 pass

As per coding guidelines: "Catch specific exceptions, not bare except: statements".

Also applies to: 155-156

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin-repos/web-ui-info/manager.py` around lines 83 - 85, The broad except
Exception blocks around the custom font loading and the other fallback (the
blocks that call ImageFont.load_default()) hide real errors; replace them with
specific exception handlers: for the font-loading try/except around
ImageFont.truetype(...) catch FileNotFoundError and OSError (or IOError) and log
the error before falling back to ImageFont.load_default(), and for the
image-related fallback catch PIL.UnidentifiedImageError and OSError (import
UnidentifiedImageError from PIL) so only expected PIL/file errors are handled
while letting unexpected exceptions surface.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/display_controller.py`:
- Around line 725-731: The throttled helper _tick_plugin_updates_throttled
currently hardcodes a 1.0s default which imposes a 1Hz cap and blocks plugins
that declare sub-second update_interval; change the function to avoid a fixed 1s
cap by (1) making the default min_interval non-blocking (e.g., 0.0) and treating
<=0 as “no global throttle” so plugin timing is driven by _tick_plugin_updates,
and (2) update the high-FPS caller that invokes _tick_plugin_updates_throttled
to pass an explicit min_interval when a global throttle is desired (or compute
and pass the minimum plugin-configured update_interval if you must enforce a
shared throttle). Update references: _tick_plugin_updates_throttled,
_tick_plugin_updates, and the _last_plugin_tick_time check to use the new
semantics so plugin-configured update_interval values are respected.

---

Nitpick comments:
In `@plugin-repos/web-ui-info/manager.py`:
- Around line 83-85: The broad except Exception blocks around the custom font
loading and the other fallback (the blocks that call ImageFont.load_default())
hide real errors; replace them with specific exception handlers: for the
font-loading try/except around ImageFont.truetype(...) catch FileNotFoundError
and OSError (or IOError) and log the error before falling back to
ImageFont.load_default(), and for the image-related fallback catch
PIL.UnidentifiedImageError and OSError (import UnidentifiedImageError from PIL)
so only expected PIL/file errors are handled while letting unexpected exceptions
surface.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4567f536-93a0-4cd3-999d-d70f227af93f

📥 Commits

Reviewing files that changed from the base of the PR and between 5ea2acd and e22efb3.

📒 Files selected for processing (3)
  • plugin-repos/web-ui-info/manager.py
  • src/display_controller.py
  • src/vegas_mode/render_pipeline.py

Chuck and others added 2 commits April 2, 2026 08:40
…tion handlers

Make _tick_plugin_updates_throttled default to no-throttle (min_interval=0)
so plugin-configured update_interval values are never silently capped.
The high-FPS call site passes an explicit 1.0s interval.

Narrow _load_font exception handler from bare Exception to
FileNotFoundError | OSError so unexpected errors surface.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When content width changes during a mid-cycle recomposition (e.g., a
plugin gains or loses items), blindly restoring the old scroll_position
and total_distance_scrolled could overshoot the new total_scroll_width
and trigger immediate false completion. Scale both values proportionally
to the new width and clamp scroll_position to stay in bounds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ChuckBuilds ChuckBuilds merged commit efe6b1f into main Apr 2, 2026
1 check passed
@ChuckBuilds ChuckBuilds deleted the fix/cpu-usage-and-scroll-issues branch April 2, 2026 12:47
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