Skip to main content
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.



Comments

  1. Well written. Show us what the browser interface looks like? :)

    ReplyDelete

Post a Comment

Popular posts from this blog

Custom made - Sometimes, it is nice to be able to build custom made things. Thanks to Damien George and all the clever people at micropython.org for making it easy. So that, to custom build a micropython is not that difficult. Why do you want to build customize firmware anyway? Well, you might want to include some functionalities of your own and removed some functionalities from the standard distribution. The choices are there for you to make. I have a few changes that I want to make in micropython. version header -kaki5 (pronounce kaki-lima) an additional thread cleanup function for esp32 add frozen modules CryptoXo and uasyncio remove help, upip, and webrepl camera C module for esp32 camera board These are accomplished by modifying and adding files. py/makeversionhdr.py py/modthread.c extra/CryptoXo.py, extra/uasyncio.py, and manifest.py mpconfigport.h main.c and modcamera.c I also want to remove some modules specifically, help, upip, and webrepl from esp32
Multi-threading : I previously used an uasyncio webcam server. This time around, I am testing a multi-thread webcam server. The result is promising. A multi-thread server seems to give a better throughput. The program logic is simpler when compared to the server based on uasyncio. The server is a four threaded application, two for port 80, one for port 81, and port 82 runs on the main thread, which blocks the REPL.  You can start a dedicated thread for port 82 if you do not want to block the REPL. I found pix/7 gives the best performance. A spe/2 will reduce the image size but give you a grayscale image. Please see my previous blog if all these seem mysterious to you. I have compiled a new firmware, MicroPython v1.11-571-g7e374d231.  You can download the new firmware from my repository at GitHub. The soft reset is not functioning properly. You need to do a hard reset. I also include four new functions in modcamera.c: pixformat agcgain aelevels aecvalue The pixformat chan
Micropython - v1.11-498 introduced a few changes in the source-code directory structure. Changes to specific files, as previously described in esp32-cam , will no longer work. A simple working summary on how to build esp32-cam firmware is described below: Make a recursive copy of ports/esp32 to ports/esp32-cam, and you will need to modify the following files: 1) ports/esp32-cam/main.c 2) ports/esp32-cam/Makefile 3) ports/esp32-cam/modcamera.c 4) ports/esp32-cam/mpconfigport.h 5) ports/esp32-cam/boards/manifest.py 6) ports/esp32-cam/boards/sdkconfig.base Or, you can just download a precompiled Micropython v1.11-498 from firmware.bin at GitHub if you want to save some work. However, I encourage you to compile the firmware yourself. You will learn a lot and you can choose to modify anything to your liking. The modcamera.c includes something new. The still photo was taken using these settings; pix =8, con =2, qua =10, and spe =2. You will understand those parameters, later