Benchmark Sederhana Web Framework Python Pilihan dengan Apache Benchmark

Sabtu ini di April 2017, kami iseng – iseng melakukan benchmarking terhadap empat web framework beberapa web framework Python. Kami mencoba benchmarking terhadap web framework seperti Bottle, Flask, Falcon, Django, Japronto, dan Sanic.

Sebenarnya benchmarking ini iseng dan tentu saja bukan acuan resmi yang dapat mempengaruhi proses bisnis atau plan development kamu jadi pengen ganti ke web framework yang ada dibawah ini. Berikut adalah beberapa batasan hardware digunakan dalam benchmarking ini:

  • Sistem Operasi: OSX
  • RAM: 4GB
  • CPU: Quadcore

Sedangkan berikut batasan perangkat lunak untuk setiap web framework:

  • Bottle: Gunicorn, Meinheld, Python2
  • Flask: Gunicorn, Meinheld, Python2
  • Falcon: Gunicorn, Meinheld, Python2
  • Django: Gunicorn, Meinheld, Python2
  • Japronto: Python3, UvLoop
  • Sanic: Python3, UvLoop

Sedangkan untuk alat benchmarking kita menggunakan Apache Benchmark yang sudah cukup dikenal oleh khalayak system tester.

Source Code

Berikut adalah source code untuk setiap web framework yang di benchmark:

Falcon:

import falcon

class HelloResource(object):
    def on_get(self, req, resp):
        resp.status = falcon.HTTP_200
        resp.body = ("Hello world!")

app = falcon.API()

hello = HelloResource()
app.add_route('/', hello)

Untuk menjalankan kode diatas digunakan perintah berikut:

$ gunicorn -w 4 --worker-class="egg:meinheld#gunicorn_worker" main:app
$ gunicorn -w 4 main:app
$ gunicorn -w 4 -k gevent main:app
$ gunicorn -w 4 -k eventlet main:app
$ gunicorn -w 4 -k tornado main:app

Flask:

from flask import Flask

# gunicorn -w 4 --worker-class="egg:meinheld#gunicorn_worker" main:app
# gunicorn -w 4 main:app

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello world!"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

Untuk menjalankan kode diatas digunakan perintah berikut:

$ gunicorn -w 4 --worker-class="egg:meinheld#gunicorn_worker" main:app
$ gunicorn -w 4 main:app

Bottle:

from bottle import route, run, template
import bottle

@route('/')
def index():
    return "Hello world"

if __name__ == "__main__":
    run(host='localhost', port=8080)

app = bottle.default_app()

Untuk menjalankan kode diatas digunakan perintah berikut:

$ gunicorn -w 4 --worker-class="egg:meinheld#gunicorn_worker" main:app
$ gunicorn -w 4 main:app

Django:

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.
def index(request):
    return HttpResponse("Hello world")

Untuk menjalankan kode diatas digunakan perintah berikut:

$ gunicorn -w 4 --worker-class="egg:meinheld#gunicorn_worker" myapp.wsgi
$ gunicorn -w 4 myapp.wsgi

Sanic:

from sanic import Sanic
from sanic.response import text

app = Sanic(__name__)

@app.route("/")
async def hello(request):
    return text('Hello world!')

app.run(host="0.0.0.0", port=8080, debug=True)

Untuk menjalankan kode diatas digunakan perintah berikut:

$ python -m sanic server.app --host=0.0.0.0 --port=8080 --workers=4

Japronto:

from japronto import Application


def hello(request):
    return request.Response(text='Hello world!')


app = Application()
app.router.add_route('/', hello)
app.run(debug=True)

Untuk menjalankan kode diatas digunakan perintah berikut:

$ python3 main.py

Hasil dan Kesimpulan

Kami menguji setiap web framework python ini dan kombinasinya dengan Gunicorn dengan menggunakan perintah berikut:

$ ab -n 1000 -c 100 http://localhost:8000/

Berikut adalah hasil ringkasan dari benchmarking yang dilakukan di localhost ini:

No  Web Framework   Engine/Gunicorn Worker  Average RPS
1   Bottle  Gunicorn/Meinheld   7793.178
2   Falcon  Gunicorn/Meinheld   7715.928
3   Japronto    UvLoop      7501.257
4   Flask   Gunicorn/Meinheld   4130.334
5   Django  Gunicorn/Meinheld   2884.538
6   Falcon  Gunicorn/Sync   2858.91
7   Bottle  Gunicorn/Sync   2725.531
8   Falcon  Gunicorn/Gevent 2522.359
9   Falcon  Gunicorn/Eventlet   2256.528
10  Falcon  Gunicorn/Tornado    1939.52
11  Flask   Gunicorn/Sync   1916.042
12  Django  Gunicorn/Sync   1536.583
13  Sanic   UvLoop      631.155

Dari percobaan diatas, dapat diambil kesimpulan:

  • Bahwa microframework WSGI seperti Bottle dan Flask memiliki keunggulan dalam jumlah request per second di banding web framework lain yang disokong oleh Gunicorn dan Python2.
  • Kehadiran Meinheld sebagai worker untuk Gunicorn, membuat Bottle dan Falcon lebih gegas ketimbang worker sync yang menjadi default worker di Gunicorn atau worker yang lainnya.
  • Japronto sebagai web framework yang dibangun diatas Python3 dan UvLoop memiliki RPS yang cukup bersaing dengan Bottle dan Falcon. Hanya saja web framework yang satu ini belum rilis dan masih dalam tahap development. Dokumentasinya pun masih jarang.

Penutup

Untuk detail benchmarking dapat diunduh report-nya di tautan http://poss.cs.upi.edu/wp-content/uploads/2017/04/python-web-framework-benchmark.ods.

Hasil benchmarking ini memang kurang tepat karena tidak dilakukan dengan deployment ke server sehingga network latency yang seharusnya terukur malah tidak menjadi bagian penting dalam benchmarking ini.

Semoga bermanfaat :D.

Leave a Reply