Simple Json Response basic test between Flask and Django

Django and Flask are two well known Python web frameworks. There are lot of benchmarks claim Flask is 2xfaster for simple JSON Response, one such is Techempower. After lookinginto the source, it struckme Django can do better!

I will compare Flask and Django for simple json response. The machine used is Macbook pro, Intel Core i5-4258U CPU @ 2.40GHz,with 8 GB Memory on OS X 10.10.3. gunicorn==19.3.0 will be used for serving WSGI application.

#flask simple app
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/index')
def index():
    return jsonify({'hello': 'world'})

if __name__ == "__main__":
    app.run()

Start the flask app, gunicorn -w 2 -b 127.0.0.1:5000 flask_app:app.

apachebench will be used for benchmarking, you can use any tool for this.

ab -n 1000 -c 2 http://localhost:5000/index
...
Server Software:        gunicorn/19.3.0
Server Hostname:        localhost
Server Port:            5000

Document Path:          /index
Document Length:        22 bytes

Concurrency Level:      2
Time taken for tests:   0.622 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      174000 bytes
HTML transferred:       22000 bytes
Requests per second:    1429.55 [#/sec] (mean)
Time per request:       1.399 [ms] (mean)
Time per request:       0.700 [ms] (mean, across all concurrent requests)
Transfer rate:          242.91 [Kbytes/sec] received

Now let’s do same thing with Django 1.8 with default settings.

#hello/views.py
from django.http import JsonResponse

# Create your views here.
def index(request):
    return JsonResponse({'hello': 'world'})

Add url('^index/$', index), in urls.py and hello app in settings.py.Start the Django app, gunicorn -w 2 -b 127.0.0.1:8000 django_app.wsgi.

ab -n 1000 -c 2 http://localhost:8000/index/
...
Server Software:        gunicorn/19.3.0
Server Hostname:        localhost
Server Port:            8000

Document Path:          /index/
Document Length:        18 bytes

Concurrency Level:      2
Time taken for tests:   0.814 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      179000 bytes
HTML transferred:       18000 bytes
Requests per second:    1228.25 [#/sec] (mean)
Time per request:       1.628 [ms] (mean)
Time per request:       0.814 [ms] (mean, across all concurrent requests)
Transfer rate:          214.70 [Kbytes/sec] received

Time taken for 1000 requests by Django is 0.814s and Flask is 0.622s. Clearly flask is faster.

Django is full fledged framework but Flask is micro framework. Django comes with lot of middlewares, contribmodels etc … Remove all those unused settings in settings.py.

Comment all middleware classes. The settings snippet looks like

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'hello',
)

MIDDLEWARE_CLASSES = (
    # 'django.contrib.sessions.middleware.SessionMiddleware',
    # 'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    # 'django.contrib.auth.middleware.AuthenticationMiddleware',
    # 'django.contrib.messages.middleware.MessageMiddleware',
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

Restart the django app and run ab -n 1000 -c 2 http://localhost:8000/index/.

...
Server Software:        gunicorn/19.3.0
Server Hostname:        localhost
Server Port:            8000

Document Path:          /index/
Document Length:        18 bytes

Concurrency Level:      2
Time taken for tests:   0.560 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      150000 bytes
HTML transferred:       18000 bytes
Requests per second:    1784.37 [#/sec] (mean)
Time per request:       1.121 [ms] (mean)
Time per request:       0.560 [ms] (mean, across all concurrent requests)
Transfer rate:          261.38 [Kbytes/sec] received

Now Django took only 0.560s for 1000 requests compared to flask 0.622s.

Now remove Django admin from urls.py, and remove all contrib apps in INSTALLED_APPS.

INSTALLED_APPS = (
#'django.contrib.admin',
#'django.contrib.auth',
#'django.contrib.contenttypes',
#'django.contrib.sessions',
#'django.contrib.messages',
#'django.contrib.staticfiles',

'hello',
)

Restart the Django app and run the benchmark ab -n 1000 -c 2 http://localhost:5000/index.

...
Server Software:        gunicorn/19.3.0
Server Hostname:        localhost
Server Port:            8000

Document Path:          /index/
Document Length:        18 bytes

Concurrency Level:      2
Time taken for tests:   0.553 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      150000 bytes
HTML transferred:       18000 bytes
Requests per second:    1806.90 [#/sec] (mean)
Time per request:       1.107 [ms] (mean)
Time per request:       0.553 [ms] (mean, across all concurrent requests)
Transfer rate:          264.68 [Kbytes/sec] received

That is much better. While developing API based application in Django tweak settings.py to getbetter performance out of Django. Source code for this benchmark can be found in Github.

See also

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.