MP webserver comparison

In a parallel thread we had some discussions about web servers to be used in conjunction with LVGL and MP.

So I made some benchmarks. I have been testing three servers: my own uwebserver https://github.com/harbaum/LittleBlockly, MicroWebSrv2 https://github.com/jczic/MicroWebSrv2 and TinyWeb https://github.com/belyalov/tinyweb

My own server is single threaded (and can thus only serve one file at a time), MicroWebSrv2 is thread based and TinyWeb uses asyncio. The later can both handle multiple connections in parallel. My test setup on a ESP32 consists of a single small web page with favicon and style sheet and two different 100kB JPG images. These are five files in total, three small ones and two big ones which somewhat resembles the blockly and codemirror setups i intend to use.

With the ESP32 at 160Mhz and nothing else in the background the results are:

MicroWebSrv2: 3.5+14sec
TinyWeb: 2+23sec
my uwebserver: 1.3+5sec

The first number is the time after which the first index.html is successfully transferred and the second number is the additional time until all five files are completely transferred. One can e.g. see that Tinyweb reacts faster and has thus an advantage over MicroWebSrv2 with small files. But MicroWebSrv2 is faster with the transfer itself and thus needs less time for the overall transfer.

But this also shows that simplicity has a significant advantage here and my trivial solution beats both significantly. I have a semi-finished version that avoids using readline which gives another advantage:

uwebserver new: 0.8+3.5sec

I also tested all at 240Mhz:

MicroWebSrv2:  3.5+12.5sec
TinyWeb: 2+20sec
uwebserver old: 1+4.5sec
uwebserver new: 0.6+3.5sec

So the CPU has an impact.

Some days ago I already tried MicroWebSrv2 in conjunction with the LVGL advanced_demo to see how much impact that has:

MicroWebSrv2 @160Mhz with chart page not visible:  4+19 sec
MicroWebSrv2 @240Mhz with chart page not visible:  4+18 sec
MicroWebSrv2 @160Mhz with chart page visible:  37+260 sec, image transfers time out
MicroWebSrv2 @240Mhz with chart page visible:  16+100 sec

So the high CPU load of the chart graphic in the demo has a huge impact on the overall performance. And in that scenario the extra 80 MHz are helpful. Still web and advanced graphics at the same time is a problem.

There are two things I plan to do:
a) try to optimize my own server somewhat. It’s sure less stable than the other two and will need some work here and there
b) try to use the http server of the espidf. This is why i asked about the generator script

I really think that a webserver is a useful addon for MP on the ESP32 and I still hope to be able to implement a useful remote display feature. I hope that WebSockets like https://github.com/danni/uwebsockets may help getting latency down compared to the current stream of http get requests. And some simple rle encoding of the image data may help speeding up the data transfer itself. But since espidf itself also offers websockets I would also like to try this with espidf.

The espidf web server would imho very much be in the spirit of MP and LVGL where the framework itself is written in C to be as fast as possible and the user programs are written in MP (and HTML) to ease application development.

I’m not an ESP32 user so this might be totally inaccurate. Would the second core be useful in this case to process server requests independently of the rendering? Right now it sounds like there is indeed not enough CPU power on one core to handle both.

I don’t think Micropython supports the second core at all. Not even with the threading module.

So using the second core for the web server would IMHO only work if the web server itself is entirely a seperste RTOS thread. But this still sounds like a nice plan to me. Running Micropython on one core and a web server on the second one with some means for data exchange between the two.

But I may be totally wrong and MP does already support the second core.

You’re right. It was in fact @amirgon himself who found race condition problems when MicroPython ran on two cores and recommended pinning tasks to one core only.

That means you would need to have a web server written in C on the second core, with some interface for talking to MicroPython glue logic.

Under some assumptions it’s possible to run Micropython on both cores.
But I’m not sure that would be a good idea because the second core is where the WiFi and TCP stack is running. Under a lot of traffic, networking workload by itself might be heavy enough to justify running it on a separate core, although I never tried to profile it.

Another option I’ve been considering in the past was running Micropython on one core and LVGL rendering on the other one.

First tests with the MP enabled esp httpd: 0.2 + 2 sec @ 160Mhz. Faster than any of the others. And of course this is the full featured thing doing all the parsing and testing that my trivial python version doesn’t.

Currently that goes through a single httpd handler which means that all transfers share the same locks. I’ll think a little more about the locks.

Thanks for the update!
Btw, any reason why not run at 240mhz?

No, no special reason. The difference between 160 and 240 is barely noticable.

How do run the esp32 httpd from micropython? Can you give me access to your tests for study?

This is not functioning stable enough yet.

Hi Till
No problem, I don’t want to use it for any production software but I want to learn.
I have read the other thread on this and I have re-compiled lv_micropython with the esp httpd enabled.
Starting from the point where you have got to, is clearly easier than starting from scratch.

I’ll create a patch this evening … I actually see all kinds of rare weird effects which all smell like memory corruption. It may help if you (or others) can reproduce this.

Also I was able to just replace the esp_http_server inside the espidf version used by MP with the latest one incl websocket support. I did not test this aspect, but the replaced server is still working as a web server.

Sounds interesting. I am currently working on a firmware for the LilyGo t-watch 2020 and a WEB server could be very interesting e.g. for settings. I was playing with picoweb and the ESP32 camera before, but never used a webserver together with lvgl.
The watch firmware is still very much “work in progress” but a few apps are already working on it.

I’ve released it at

Please give it a try.