Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to sleep instead of busy waiting when limiting refresh rate #1563

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

somechris
Copy link

On single core boards, busy waiting renders the system unresponsive. We add the --led-no-busy-waiting flag, to allow the process to sleep instead of busy waiting, thereby freeing up CPU cycles for other processes at the cost of slightly less accurate frame timing.

On a Raspberry Pi 3B on two 32x32 panels, busy waiting keeps a core 98% busy. Sleeping reduces it to 14%.

On a Raspberry Zero on two 32x32 panels, busy waiting keeps the single core 95% busy and gives an unresponsive system. Sleeping reduces it to 32% and keeps the system responsive.

Sleeping degrades the timing accuracy a bit, but is still good enough by a far margin for many uses. The following numbers are for driving two 32x32 panels and averaging the refresh rate across a minute (the 1kHz refresh rate limit is of course not reached, and is only there to make sure that the relevant code path is taken):

                                               +--------------+-----------+
                                               | busy waiting | sleeping  |

+--------------------------------------------------+--------------+-----------+
| Raspberry Pi 3B, limit 70Hz, hardw. pulsing | 70.000Hz | 69.977Hz |
| Raspberry Pi 3B, limit 70Hz, no hardw. pulsing | 70.000Hz | 69.977Hz |
| Raspberry Pi 3B, limit 1kHz, hardw. pulsing | 430.824Hz | 430.855Hz |
| Raspberry Pi 3B, limit 1kHz, no hardw. pulsing | 365.498Hz | 365.456Hz |
| Raspberry Pi Zero, limit 70Hz, hardw. pulsing | 69.986Hz | 69.643Hz |
| Raspberry Pi Zero, limit 70Hz, no hardw. pulsing | 69.986Hz | 69.638Hz |
| Raspberry Pi Zero, limit 1kHz, hardw. pulsing | 263.877Hz | 264.538Hz |
| Raspberry Pi Zero, limit 1kHz, no hardw. pulsing | 233.166Hz | 231.650Hz |
+--------------------------------------------------+--------------+-----------+

On single core boards, busy waiting renders the system unresponsive.
We add the --led-no-busy-waiting flag, to allow the process to sleep
instead of busy waiting, thereby freeing up CPU cycles for other
processes at the cost of slightly less accurate frame timing.

On a Raspberry Pi 3B on two 32x32 panels, busy waiting keeps a core
98% busy. Sleeping reduces it to 14%.

On a Raspberry Zero on two 32x32 panels, busy waiting keeps the single
core 95% busy and gives an unresponsive system. Sleeping reduces it to
32% and keeps the system responsive.

Sleeping degrades the timing accuracy a bit, but is still good enough
by a far margin for many uses. The following numbers are for driving
two 32x32 panels and averaging the refresh rate across a minute (the
1kHz refresh rate limit is of course not reached, and is only there to
make sure that the relevant code path is taken):

                                                   +--------------+-----------+
                                                   | busy waiting | sleeping  |
+--------------------------------------------------+--------------+-----------+
| Raspberry Pi 3B, limit 70Hz, hardw. pulsing      |  70.000Hz    |  69.977Hz |
| Raspberry Pi 3B, limit 70Hz, no hardw. pulsing   |  70.000Hz    |  69.977Hz |
| Raspberry Pi 3B, limit 1kHz, hardw. pulsing      | 430.824Hz    | 430.855Hz |
| Raspberry Pi 3B, limit 1kHz, no hardw. pulsing   | 365.498Hz    | 365.456Hz |
| Raspberry Pi Zero, limit 70Hz, hardw. pulsing    |  69.986Hz    |  69.643Hz |
| Raspberry Pi Zero, limit 70Hz, no hardw. pulsing |  69.986Hz    |  69.638Hz |
| Raspberry Pi Zero, limit 1kHz, hardw. pulsing    | 263.877Hz    | 264.538Hz |
| Raspberry Pi Zero, limit 1kHz, no hardw. pulsing | 233.166Hz    | 231.650Hz |
+--------------------------------------------------+--------------+-----------+
@wawanbreton
Copy link

Hi @somechris, thanks for this improvement, this really helps lowering the CPU load, very useful on a Pi Zero :)
I would even suggest adding it without an option, I fail to see a case where you would actually want to do an active wait. Maybe the timing is a bit less perfect indeed, but as long as you have a decent refresh rate, the display is as good !

@hzeller
Copy link
Owner

hzeller commented Feb 11, 2024

Nice! Thanks @somechris
Sorry, just seeing this now as @wawanbreton 's mail bumped the thread. The notifications on github are easy to miss.

The code looks great. Thanks for taking care that this is an inverted option so that memsetting the struct to zero would be backward compatible.

So code-wise, I think we're ready to merge, but you should also add the description of this flag in a paragraph in the README where --led-limit-refresh is explained. If it is in the README, it is easier discoverable. Can you update the PR ?

GitHub's Markdown renderer underlined the whole text from
`--led-no-drop-privs` until the start of the next section, which made
it hard to read.

Be converting `A` tag from self-closing to explicitly closed tag,
GitHub renders the file without the extra underlining again, which
makes it easier to read.
@somechris
Copy link
Author

Can you update the PR ?

Done :-)

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.

None yet

3 participants