LinkedIn Sourceforge Twitter

Vincent's Blog

Pleasure in the job puts perfection in the work (Aristote)

Fast asynchronous python web server is really fast

Posted on 2018-11-01 13:18:00 from Vincent in OpenBSD fapws

Since several years, I'm using fapws3 for few of my websites. Mainly for servers where resources are limited.

Fapws3 has not received lot of commits since long time, so, this post will show my investigation to find an other tiny and fast python web server running python3

What is the context ?

In my case, I need very small memory foot print for the webserver. It runs on small machines having 2GB or 4GB of ram, and this ram is there for other services than for a webserver. The webserver is just there to present so dashboard and few parameters of the services running on the machine.

As consequence of this element, I do not want to see multi threaded web servers because they eat all my memory RAM.

And, important, I'm programming mainly in python. This is not optimal for the memory. Maybe lua would be better, this is an other topic.

What is the need ?

Fapws3 is running quite well for my needs (except few bugs I'm correcting here and there). Check my git repository.

Nevertheless, I'm more and more using python3 and fapws3 is still requiring python2.

Thus, I'm looking for a python3 module that would allow me to replace my fapws3 instances.

And for sure, all of them are running OpenBSD

How did I compare them ?

The scenario to compare the different solutions is by using a simple page displaying "Hello World!".

I'm benchmarking it via the ApacheBenchmark tool by always doing this:

ab -n50000 -c1000

I other words, I'm requesting 50.000 requests with a concurrency of 1.000.

In all cases, the machine is the same: a DELL E5450 running OpenBSD 6.4

What did I test ?

Tested tools


Let's first take a reference with my last fapws3 version (here). Please note, that this is not the same version as what we can find on the author's github repository.

In my case, I'm doing the install by doing:

doas python2.7 install

once I unzip the code.


netius can be compiled and installed by simply doing a

doas pip3.6 install netius


sanic can be installed by simply doing a:

doas pip3.6 install sanic


werkzeug can be installed by doing a simple:

doas pip3.6 install werkzeug


With bjoern, the pip3.6 install does not work.
After some investigations, I've discovered that there is compilation decisions (like this one) where OpenBSD is not listed.

The problem is that the sendfile command is not existing on OpenBSD. This command must be replaced, most probably by the write command.

I've not investigate more.


japronto can be installed via the wimple:

doas sip3.6 install japronto

But, when I run the "hello" sample script, I have he following error message:

Accepting connections on
Exception in callback UVTransport._call_connection_made
handle: <Handle UVTransport._call_connection_made>
Traceback (most recent call last):
  File "uvloop/cbhandles.pyx", line 67, in uvloop.loop.Handle._run
  File "uvloop/handles/tcp.pyx", line 151, in uvloop.loop.TCPTransport._call_connection_made
  File "uvloop/handles/basetransport.pyx", line 152, in uvloop.loop.UVBaseTransport._call_connection_made
  File "uvloop/handles/basetransport.pyx", line 149, in uvloop.loop.UVBaseTransport._call_connection_made
SystemError: NULL result without error in PyObject_Call


As reference, I've also tested the httpd web server provided by OpenBSD.

If such case, I've just used the file exiting in /var/www/htdocs and called index.html.

My /etec/httpd.conf file is like this:

prefork 1
server "default" {
        listen on * port 80

As you see I just request to have only 1 running process, just to be coherent with the context of this test.

Having httpd is such comparison it just to compare python based web server versus a full C web server. For my needs, httpd is not an option because, I have to setup a fastcgi server close to it. For my case, having a small python web server delivering directly html pages is much efficient in term of memory foot print.


All details results are here

By comparing the number of request per seconds, the total time taken by the test and the RSS memory, I have the following results:

(Number of requests per seconds)

(total time take for 50.000 requests with a concurrency of 1.000)

(RSS memory used during the test)


Fapws3 is still the fasted and the lightest.

The big total time for netius and werkzeug are due to few request which take lot of time 42sec (as reported by ApacheBenchmark)


Despite written long ago (+7 years), fapws3 is still quite good for this simple "hello world" test.

So, which tool do I select ? The answer is NONE.

This benchmark does not allow me to see which tool is the best. Fapws3 is still interesting, but is not running python3. bjoern needs to be adapted to run correctly.

31, 25
displayed: 7519

What is the second letter of the word Moon?