TinySQL

This article provides information about the Python frameworks and compares them with WSGI-synchronous solutions from the strengths and weaknesses point of view.

A simple solution

for small sites

  • 100% portability
  • Simple interface
  • The speed is limited only by the capacity your HDD
  • API for those who wish to spread the UI and ServerSide (in development)

Python web-frameworks

This article provides information about the Python frameworks and compares them with WSGI-synchronous solutions from the strengths and weaknesses point of view.

The following frameworks considered (description taken from their sites)

  • Aiohttp 0.16.3 - asynchronous framework based on Asyncio;
  • Bottle 0.12.8 - fast, simple and lightweight WSGI microframework;
  • Django 1.8.2 - web framework for perfectionists with deadlines burning;
  • Falcon 0.3.0 - high-performance framework for building cloud API;
  • Flask 0.10.1 - microframework based on Werkzeug, Jinja2 and good intentions;
  • Muffin 0.0.88 - asynchronous framework based on Asyncio è Aiohttp;
  • Pyramid 1.5.7 - small, fast and intuitive web framework;
  • Tornado 4.2 - asynchronous networking library and a web framework;

Test procedure

Tests were carried out on Amazon EC2 t2.medium server. To create a load used WRK utility running on the same server with the following parameters:

wrk -d30s -t12 -c400 [URL]

All applications (except for the Tornado) were run using Gunicorn (2 for each process). For synchronous WSGI libraries used Meinheld worker.

Tornado has launched the process of using including web-server.

All tests were conducted using Python 2.7.6.

Each application was tested on three main scenarios:

  • JSON-test - encode small object in JSON and return to the client.
  • Remote-test - download response from another server and return it to the client.
  • Complete-test - using ORM to load a collection of objects from the database, add to it and render the list in a template.

The first scenario is the simplest request of object to JSON encoding. It shows the speed of the HTTP-request processing.

The second scenario shows how well the framework copes with long waiting transactions while processing the request.

The third scenario is an integrated test and simulates real life by using of a database, ORM, templating work.

Postgresql database used as default.

Source code is presented at Github.

Results

Encode an object to JSON and return result

Name50% (ms)75% (ms)Avg (ms)Req/s
Falcon19.2419.8119.1920677.13
Bottle24.7726.2325.0615761.45
Pyramid41.7543.4941.639402.69
Flask64.3271.5965.686023.4
Aiohttp91.67103.1108.014093.41
Django103.2112.19103.363696.9
Muffin108.07115.09171.563575.36
Tornado138.24149.84136.872829.72

In the first test, simple synchronous frameworks were the best. Asynchronous frameworks showed worse results.

 

Load a response from remote server and return as response

Name50% (ms)75% (ms)Avg (ms)Req/sTimeouts
Aiohttp358.08369.08338.941120.27 
Muffin372.95428.75376.981019.76 
Tornado1994.392069.251928.31194.37 
Pyramid3295.110518.926673.7819.35338
Falcon3196.2312976.846696.1719.28328
Flask3306.8811690.86824.8819.16363
Bottle3363.749911.846403.9219.09335
Django3317.6412954.236918.6418.96300

To understand the results of this test is necessary to clarify that the application accesses the nginx configured to respond with 100ms latency. Because of this, the results are very close to synchronous frameworks.

 

Load data from database with ORM and render to template

Name50% (ms)75% (ms)Avg (ms)Req/sTimeouts
Aiohttp151.78156.9254.751004.82236
Muffin420.14485.41552.7819.62 
Bottle613.5630.171062.86451.34178
Tornado937.37988.86910.06418.36 
Falcon766.75805.351457.99350.2681
Pyramid562.44601.49812.43248.42235
Flask1032.631649.891465.25222.78496
Django1610.461976.442632.3688.5742

Based on test results, I suggest using Bottle framework as an optimal solution. Besides, this framework is rather simple and intuitive comparing to the others.


Site developer - Site! ltd.