Time-multiplexing - The _threads modules for esp32 is a time-multiplex multi-threading implementation on a single CPU (APP-CPU) where the tasks take turns to run.
Let say we have four tasks A, B, C, and D. Each task takes 100 microseconds to complete.
If these tasks are arranged to run in sequence A->B->C->D then the whole process will take 400 microseconds.
What if we run these tasks concurrently in 4 separate threads, A||B||C||D. How long the process takes to complete? The answer is 400 microseconds also.
We have not made our concurrent tasks running any faster. What is the point of multi-threading then? The ability to use multi-threading in our codes will make our programs more responsive to external events.
Consider this; let say our threads scheduler allocates a 25-microsecond slot to each running task, in a round-robin style.
Each tasks are allocated 4 slots of 25 microseconds. What happen conceptual is like this;
A1||B1||C1||D1||A2||B2||C2||D2||A3||B3||C3||D3||A4||B4||C4||D4
Let say task B listen to a network socket at B2 and task C read an input pin at C3.
With sequential execution, B2 can only happen after 125 microseconds and C3 have to wait for 275 microseconds.
With multi-threading, B2 can happen after 125 microseconds (after A2) and C3 after 250 microseconds (after A3, B2 is waiting for input).
What if you have codes that get blocked in B2?
In sequential execution, we will get A1->A2->A3->A4->B1->B2 and our program will hang in B2. Only task A is allowed to complete its execution, all the rest will have to wait for B2 to get unblock.
With multi-threading A, C, and D will run to completion. Task B got blocked in B2.
Multi-threading is a good thing to have. It is such an important feature that Pycom Limited sponsored Damien George to incorporate the _thread module into MicroPython for esp32.
Many will program a multi-threading server with the main thread waiting for requests in a forever loop and service each new request in a new thread as it arrived.
This is how we normally program a web server.
Well so far so good, except your MicroPython server running on an esp32 will only be able to service a limited number of requests at any one time.
My mth_webcam.py mth_webcam.py pre-allocated and use only 4 threads.
The resources held by older inactive threads are not freed for recycling straight away, it takes time. We need to wait for a while.
A simple thread pre-allocation method will work most of the time.
I took the liberty of changing the _thread module implementation for esp32 to incorporate _thread.cleanup() function based on mp_thread_deinit(void) of ports/esp32/mpthreadport.c code file.
As it is, the mp_thread_deinit() will wipe out all threads, except the thread in which the function is called. This is a drastic measure, and you want to use this if you suspect that all threads are blocked for whatever reason.
I exposed the mp_thread_deinit() as a new API named _thread.cleanup() in py/modthread.c code file.
While I am at it, I also, modify py/makeversionhdr.py to give MicroPython a version tag that differs from the official distribution.
The result?
MicroPython v1.11-631-gb76f0a73b-kaki5 on 2019-11-19; ESP32 module with ESP32
>>> import _thread as th
>>> dir(th)
['__class__', '__name__', 'LockType', 'allocate_lock', 'cleanup', 'exit', 'get_ident', 'stack_size', 'start_new_thread']
I have tested the robustness of my _thread module by running a test script for about one hour. There was no need to use _thread.clenup(), however, I need to wait for resources to be free before I manged to do _thread.start_new_thread(). I had to stop the execution loop with KeyboardInterrupt. The module had managed to create 172989 threads and having 3 active threads at the time of interrupt.
The "-kaki5" tags my modified version of MicroPython, so I think that is ok. When one sees "-kaki5" and their scripts crash, blame me not the micropython.org's developers.
The use of the firmware is without warranty of any kind. Feel free to use it. You are responsible for your deployment.
The kaki5 or kaki lima is a Malay word that translates to the pavement or pedestrian sidewalk. In Malaysia, and many other South-East Asian countries, street vendors peddling street-foods and cheap stuff on kaki lima.
Let say we have four tasks A, B, C, and D. Each task takes 100 microseconds to complete.
If these tasks are arranged to run in sequence A->B->C->D then the whole process will take 400 microseconds.
What if we run these tasks concurrently in 4 separate threads, A||B||C||D. How long the process takes to complete? The answer is 400 microseconds also.
We have not made our concurrent tasks running any faster. What is the point of multi-threading then? The ability to use multi-threading in our codes will make our programs more responsive to external events.
Consider this; let say our threads scheduler allocates a 25-microsecond slot to each running task, in a round-robin style.
Each tasks are allocated 4 slots of 25 microseconds. What happen conceptual is like this;
A1||B1||C1||D1||A2||B2||C2||D2||A3||B3||C3||D3||A4||B4||C4||D4
Let say task B listen to a network socket at B2 and task C read an input pin at C3.
With sequential execution, B2 can only happen after 125 microseconds and C3 have to wait for 275 microseconds.
With multi-threading, B2 can happen after 125 microseconds (after A2) and C3 after 250 microseconds (after A3, B2 is waiting for input).
What if you have codes that get blocked in B2?
In sequential execution, we will get A1->A2->A3->A4->B1->B2 and our program will hang in B2. Only task A is allowed to complete its execution, all the rest will have to wait for B2 to get unblock.
With multi-threading A, C, and D will run to completion. Task B got blocked in B2.
Multi-threading is a good thing to have. It is such an important feature that Pycom Limited sponsored Damien George to incorporate the _thread module into MicroPython for esp32.
Many will program a multi-threading server with the main thread waiting for requests in a forever loop and service each new request in a new thread as it arrived.
This is how we normally program a web server.
Well so far so good, except your MicroPython server running on an esp32 will only be able to service a limited number of requests at any one time.
My mth_webcam.py mth_webcam.py pre-allocated and use only 4 threads.
The resources held by older inactive threads are not freed for recycling straight away, it takes time. We need to wait for a while.
A simple thread pre-allocation method will work most of the time.
I took the liberty of changing the _thread module implementation for esp32 to incorporate _thread.cleanup() function based on mp_thread_deinit(void) of ports/esp32/mpthreadport.c code file.
As it is, the mp_thread_deinit() will wipe out all threads, except the thread in which the function is called. This is a drastic measure, and you want to use this if you suspect that all threads are blocked for whatever reason.
I exposed the mp_thread_deinit() as a new API named _thread.cleanup() in py/modthread.c code file.
While I am at it, I also, modify py/makeversionhdr.py to give MicroPython a version tag that differs from the official distribution.
The result?
MicroPython v1.11-631-gb76f0a73b-kaki5 on 2019-11-19; ESP32 module with ESP32
>>> import _thread as th
>>> dir(th)
['__class__', '__name__', 'LockType', 'allocate_lock', 'cleanup', 'exit', 'get_ident', 'stack_size', 'start_new_thread']
I have tested the robustness of my _thread module by running a test script for about one hour. There was no need to use _thread.clenup(), however, I need to wait for resources to be free before I manged to do _thread.start_new_thread(). I had to stop the execution loop with KeyboardInterrupt. The module had managed to create 172989 threads and having 3 active threads at the time of interrupt.
The "-kaki5" tags my modified version of MicroPython, so I think that is ok. When one sees "-kaki5" and their scripts crash, blame me not the micropython.org's developers.
The use of the firmware is without warranty of any kind. Feel free to use it. You are responsible for your deployment.
The kaki5 or kaki lima is a Malay word that translates to the pavement or pedestrian sidewalk. In Malaysia, and many other South-East Asian countries, street vendors peddling street-foods and cheap stuff on kaki lima.
Well written. Show us what the browser interface looks like? :)
ReplyDelete