Skip to content

perf: reduce daemon CPU usage by ~80% - #20

Open
iksaif wants to merge 4 commits into
pimoroni:masterfrom
iksaif:perf-daemon-optimizations
Open

perf: reduce daemon CPU usage by ~80%#20
iksaif wants to merge 4 commits into
pimoroni:masterfrom
iksaif:perf-daemon-optimizations

Conversation

@iksaif

@iksaif iksaif commented Aug 22, 2026

Copy link
Copy Markdown

perf: reduce daemon CPU usage by ~80%

Stacked PR 1 of 3 — base for #21 and #22.
Review in order: #20#21#22.

The plasma daemon was consuming up to 20% CPU on a Raspberry Pi even when displaying a static color. This PR addresses several performance issues:

Changes

  • Skip redundant LED updates for static colors: When showing a solid color (no pattern), plasma.show() is only called when the color or brightness actually changes, instead of being called every frame forever
  • Skip redundant pattern re-rendering: When displaying an animated PNG pattern, skip re-rendering if the animation row hasn't advanced since the last frame
  • Fix FIFO readline busy-wait: Replace the time.time() polling loop with select.select() for proper blocking I/O, eliminating CPU spin while waiting for commands
  • Cache loaded PNG patterns: Patterns are now cached in memory after first load instead of being re-parsed from disk on every pattern switch
  • Clamp FPS to minimum 1: Prevents division-by-zero or negative framerate from locking up the daemon

Benchmark

CPU (static color, 30 FPS)
Before ~15-20%
After ~0.1%

Tests

9 unit tests covering FIFO select.select() usage, pattern caching, needs_update flag behaviour (static color, colour change, brightness change), and FPS clamping. All pass alongside the existing test suite.

@Gadgetoid

Copy link
Copy Markdown
Member

Thank you!

Test fail is extremely stale CI, which needs some TLC. I was about to suggest it would fail, but it beat me to it.

House style across the board has been to rebuild libraries on top of our Python boilerplate. plasma is a bit of an outlier, though, so it hasn't been updated yet.

Latest boilerplate is here: pimoroni/boilerplate-python#21 if you want to give it a shot (I don't expect you to, I'm just not sure when I'll get to it). Though it's probably a better use of time to just fix the CI breaks here rather than a full blown rebuild.

@Gadgetoid

Copy link
Copy Markdown
Member

Okay currently looking at repacking this, wish me luck!

@Gadgetoid

Copy link
Copy Markdown
Member

Just a - not - small change 💀 - #23

CI is passing, though.

@iksaif

iksaif commented Aug 23, 2026

Copy link
Copy Markdown
Author

Great, I'll rebase my PRs once #23 is merged !

@Gadgetoid

Copy link
Copy Markdown
Member

Right, sorted!

iksaif added 2 commits August 25, 2026 14:18
- Skip redundant plasma.show() calls when color/brightness hasn't
  changed (solid colors now only update once instead of every frame)
- Skip pattern re-rendering when the animation row hasn't advanced
- Replace FIFO readline busy-wait (time.time() polling loop) with
  select.select() for proper blocking I/O
- Cache loaded PNG patterns instead of re-parsing on every switch
Clearing the flag inside the set_all() branch meant the buffer was
written but never latched to the hardware, so solid colours never
displayed. Patterns were unaffected because that branch leaves the
flag set.
@iksaif
iksaif force-pushed the perf-daemon-optimizations branch from 7067c76 to b3da94f Compare August 25, 2026 12:21
Tests cover:
- FIFO.readline uses select.select for blocking I/O
- Pattern caching avoids re-reading from disk
- needs_update flag ensures show() only fires on state changes
- Static color: show() called once, not every frame
- Color/brightness changes trigger show()
- FPS clamped to minimum 1
@iksaif

iksaif commented Sep 2, 2026

Copy link
Copy Markdown
Author

👋 this (and the others) should be ready now

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.

2 participants