Thanks to visit codestin.com
Credit goes to github.com

Skip to content

esp32: Sleep in MICROPY_EVENT_POLL_HOOK to free up GIL and cycles for other threads #8351

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

Conversation

DvdGiessen
Copy link
Contributor

@DvdGiessen DvdGiessen commented Feb 24, 2022

Currently on the ESP32 the REPL holds the GIL while sleeping in wait for input, blocking other threads significantly.

This can easily be observed by running a thread that is both busy and regularly releases the GIL (for example a loop doing something then sleeping a few ms after each iteration). When the main task is at the REPL, the thread is significantly stalled. If the main task is manually made to release the GIL (for example, by calling utime.sleep_ms(500)) the other thread can be seen immediately working at the expected speed again.

This change releases the GIL while sleeping and waiting for a new character, thus allowing other threads to acquire the GIL in the meantime and resolving the issue.

Note that MICROPY_EVENT_POLL_HOOK already releases and re-acquires the GIL. So an optional improvements might be using an alternative version of that hook here, so we don't have to release and acquire the lock twice. Left that out for now to keep the patch simple.

EDIT:
Additionally, there are various instances in where blocking functions run MICROPY_EVENT_POLL_HOOK in a loop while they wait for a certain event / condition. For example the uselect methods poll objects to determine whether data is available, but uses 100% of CPU while it does, constantly calling MICROPY_EVENT_POLL_HOOK in the process.

The MICROPY_EVENT_POLL_HOOK macro is only ever used in waiting loops, where (if threads are enabled) it makes sense to yield for at a single tick so that these loops do not consume all CPU cycles but instead other threads may execute. (In fact, the thing these loops wait for may even indirectly or directly depend on another task being able to run.)

This change moves the sleep that was inside the REPL input function to inside the MICROPY_EVENT_POLL_HOOK macro, where the GIL is already being released, solving both the blocking REPL issue and the 100% CPU use issue at the same time.

@dpgeorge
Copy link
Member

So an optional improvements might be using an alternative version of that hook here, so we don't have to release and acquire the lock twice

Considering that mp_hal_stdin_rx_chr() is not performance critical, it's probably OK to not make such an optimisation.

But an interesting question is whether ulTaskNotifyTake(pdFALSE, 1); should be added to MICROPY_EVENT_POLL_HOOK unconditionally and used in all locations that macro is used...

If MicroPython threads are enabled, loops waiting for an incoming event should
release the GIL and suspend, allowing other tasks to run while they wait.

Signed-off-by: Daniël van de Giessen <[email protected]>
@DvdGiessen DvdGiessen force-pushed the esp32_release_gil_stdinrxchar branch from 734b94c to badb5ca Compare March 1, 2022 19:50
@DvdGiessen
Copy link
Contributor Author

Yes, having looked at everywhere that macro is used that actually makes much more sense. It's only ever used in waiting loops, so sleeping should probably be the default behaviour if threads are enabled.

In fact that is also the solution for another bug that was next on my list to look into (uselect using 100% CPU). :)

Updated PR with this change.

@DvdGiessen DvdGiessen changed the title esp32/mphalport: Release GIL while sleeping in stdin_rx_char. esp32: Sleep in MICROPY_EVENT_POLL_HOOK to free up GIL and cycles for other threads Mar 1, 2022
@dpgeorge
Copy link
Member

dpgeorge commented Mar 2, 2022

Fantastic!

I tested this PR against the thread test suite and it still runs and passes.

Merged in 665f0e2, with an update of the commit message to put most of the above explanation in it.

Thank you very much!

@dpgeorge dpgeorge closed this Mar 2, 2022
@Tangerino
Copy link

Not sure if was this new change or the combination of the new mpy format I can see a clear general performance improvement.
Boot time + run time.
Awesome!

Wind-stormger pushed a commit to BPI-STEAM/micropython that referenced this pull request Sep 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants