Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Benchmark: Django + ((Gunicorn + sync worker) || (gunicorn + gevent worker)). Aide sur la compréhension d'un résultat.

+1 vote

Je suis actuellement en train de travailler sur un benchmark me permettant d'imager (je l'espère) les bénéfices d'une bascule sur des workers asynchrone du côté de notre Gunicorn. Pour ce faire j'ai créé un projet Django se lançant soit sous Gunicorn + Sync soit sous Gunicorn + Gevent (merci docker), disponible ici.

A l'instant T, trois tests sont disponibles, le premier est une vue retournant un Json, le second est une vue faisant un appel externe et le dernier insère des données en base de données.

Pour les deux derniers tests les résultats sont ceux attendu. À savoir, qu'un plus grand nombre de requêtes est traité sous Gevent.

Le problème qui se pose concerne donc le premier test. Je m'attendais à obtenir des résultats similaires quel que soit le type de worker, hors les résultats sous Gevent sont bien moins bons.

Pour ceux qui ont la flemme d'aller voir sur le repository github je colle le code ci-dessous avec un résumé des tests.

#views.py 
def simple_json(request):
    return HttpResponse(json.dumps({"a": "b"}))

#sync
ab -c 4 -n 1000 http://localhost:8000/simple_json
Temp total = 0.883  requète/sc = 1133,114

ab -c 8 -n 1000 http://localhost:8000/simple_json
Temp total = 0.720  requète/sc = 1392.414

ab -c 16 -n 1000 http://localhost:8000/simple_json
Temp total = 0.648  requète/sc = 1544.994

#gevent
ab -c 4 -n 1000 http://localhost:8001/simple_json
Temp total = 1.159  requète/sc = 863.574

ab -c 8 -n 1000 http://localhost:8000/simple_json
Temp total = 1.070  requète/sc = 937.016

ab -c 16 -n 1000 http://localhost:8000/simple_json
Temp total = 1.038  requète/sc = 965.31

La seule hypothèse que je peux émettre actuellement est la suivante :

La gestion de la boucle d'événement et des greenlets à l'intérieur de nos workers serait plus important en termes de temps que les réels gains de l'asynchronisme sur un cas si simple.

Ça vous semble plausible ? Voyez-vous d'autres choses ?

demandé 2-Nov-2016 par vmonte (196 points)

gevent me posait plein de problèmes avec la DB, j'ai du retourner à sync.

D'ailleurs il a fallu ajouter un autocommit = True dans les settings .

Je serai curieux de savoir si dans ton test tu prends en compte des écritures / delete de DB avec ces différents class workers.

Comme ça remonte à 2 ans (avec un DJango 1.5.1) je n'ai plus d'info à donner sur le type de problème exact avec gevent malheureusement.

1 Réponse

0 votes

Je n'ai pas de réponse immédiate à fournir à ton use-case, car comme dirait Victor Stinner, il est très difficile désormais d'obtenir un benchmark stable et représentatif.

Cependant il existe un projet qui fait la part belle aux performances et aux benchmark, et un projet avec Django ainsi qu'un autre avec aiohttp y figurent.

https://github.com/TechEmpower/FrameworkBenchmarks

Pour y avoir touché un peu, aiohttp a des performances juste folles surtout lorsque uvloop (merci Yuri) est utilisé à la place de la boucle d'événement standard de asyncio.

Concernant Django, le constat est un peu plus mitigé de part sa nature même qui est encore volontairement très synchrone. Pas de possibilité d'asynchronisme sur les transactions en base de données et le seul levier est sur la charge des workers HTTP (avec Gunicorn ou uWSGI).

répondu 3-Nov-2016 par debnet (990 points)

+1 pour ta remarque sur les benchmarks, j'essaie d'avoir des tendances globales.

Oui les performances de aiohttp semblent prometteuses, le problème qui se pose est que le projet sur lequel je bosse est déjà entièrement codé sur Django.

Pour Django, je lis un peu partout que ses performances peuvent être améliorées quand ils tournent sur des workers gevent. (Ce que j'essaie de prouver)
Le benchmark présent sur le repo github montre bien que les opérations I/O sont bien impactées par ce type de worker mais on dirait que pour les autres opérations il soit plus long. Ce que j'essaie de comprendre.

...