Python asyncio en pratique : mesures reelles

Python est le langage le plus similaire a PHP en termes de modele d'execution : interprete, monothread (GIL), avec une dominance des frameworks synchrones. La transition du Python synchrone (Flask, Django + Gunicorn) vers l'asynchrone (FastAPI, aiohttp, Starlette + Uvicorn) est une analogie precise de la transition de PHP-FPM vers un runtime base sur les coroutines.

Voici une collection de cas de production, de benchmarks independants et de mesures.


1. Production : Duolingo -- migration vers Python async (+40% de debit)

Duolingo est la plus grande plateforme d'apprentissage des langues (500M+ utilisateurs). Le backend est ecrit en Python.

En 2025, l'equipe a commence une migration systematique des services du Python synchrone vers l'asynchrone.

MetriqueResultat
Debit par instance+40%
Economies de couts AWS EC2~30% par service migre

Les auteurs notent qu'apres avoir construit l'infrastructure async, la migration des services individuels s'est averee "assez simple".

Source : How We Started Our Async Python Migration (Duolingo Blog, 2025)


2. Production : Super.com -- reduction des couts de 90%

Super.com (anciennement Snaptravel) est un service de recherche d'hotels et de remises. Leur moteur de recherche gere 1 000+ req/s, ingere plus de 1 To de donnees par jour et traite plus d'1 M$ de ventes quotidiennes.

Caracteristique cle de la charge de travail : chaque requete effectue 40+ appels reseau vers des API tierces. C'est un profil purement I/O-bound -- un candidat ideal pour les coroutines.

L'equipe a migre de Flask (synchrone, AWS Lambda) vers Quart (ASGI, EC2).

MetriqueFlask (Lambda)Quart (ASGI)Changement
Couts d'infrastructure~1 000 $/jour~50 $/jour-90%
Debit~150 req/s300+ req/s2x
Erreurs aux heures de pointeReference-95%-95%
LatenceReference-50%2x plus rapide

Economies de 950 $/jour × 365 = ~350 000 $/an sur un seul service.

Source : How we optimized service performance using Quart ASGI and reduced costs by 90% (Super.com, Medium)


3. Production : Instagram -- asyncio a l'echelle de 500M DAU

Instagram sert plus de 500 millions d'utilisateurs actifs quotidiens sur un backend Django.

Jimmy Lai (ingenieur Instagram) a decrit la migration vers asyncio dans une presentation au PyCon Taiwan 2018 :

  • Remplacement de requests par aiohttp pour les appels HTTP
  • Migration du RPC interne vers asyncio
  • Amelioration des performances de l'API et reduction du temps d'inactivite CPU

Defis : surcharge CPU elevee d'asyncio a l'echelle d'Instagram, necessite de detection automatisee des appels bloquants par analyse statique du code.

Source : The journey of asyncio adoption in Instagram (PyCon Taiwan 2018)


4. Production : Feature Store -- des threads vers asyncio (-40% de latence)

Le service Feature Store a migre du multithreading Python vers asyncio.

MetriqueThreadsAsyncioChangement
LatenceReference-40%-40%
Consommation RAM18 Go (centaines de threads)Nettement moinsReduction substantielle

La migration a ete effectuee en trois phases avec un partage de trafic 50/50 en production pour validation.

Source : How We Migrated from Python Multithreading to Asyncio (Medium)


5. Production : Talk Python -- Flask vers Quart (-81% de latence)

Talk Python est l'un des plus grands podcasts Python et plateformes d'apprentissage. L'auteur (Michael Kennedy) a reecrit le site de Flask (synchrone) vers Quart (Flask asynchrone).

MetriqueFlaskQuartChangement
Temps de reponse (exemple)42 ms8 ms-81%
Bugs apres migration--2Minimal

L'auteur note : lors des tests de charge, le maximum de req/s differait insignifiamment car les requetes MongoDB prenaient <1 ms. Le gain apparait lors du traitement de requetes concurrentes -- lorsque plusieurs clients accedent simultanement au serveur.

Source : Talk Python rewritten in Quart (async Flask)


6. Microsoft Azure Functions -- uvloop comme standard

Microsoft a inclus uvloop -- une boucle d'evenements rapide basee sur libuv -- comme defaut pour Azure Functions sur Python 3.13+.

Testasyncio standarduvloopAmelioration
10K requetes, 50 VU (local)515 req/s565 req/s+10%
5 min, 100 VU (Azure)1 898 req/s1 961 req/s+3%
500 VU (local)720 req/s772 req/s+7%

La boucle d'evenements standard a 500 VU a montre ~2% de pertes de requetes. uvloop -- zero erreur.

Source : Faster Python on Azure Functions with uvloop (Microsoft, 2025)


7. Benchmark : taches I/O-bound -- asyncio 130x plus rapide

Comparaison directe des modeles de concurrence sur une tache de telechargement de 10 000 URLs :

ModeleTempsDebitErreurs
Synchrone~1 800 s~11 Ko/s--
Threads (100)~85 s~238 Ko/sFaible
Asyncio14 s1 435 Ko/s0,06%

Asyncio : 130x plus rapide que le code synchrone, 6x plus rapide que les threads.

Pour les taches CPU-bound, asyncio n'apporte aucun avantage (temps identique, +44% de consommation memoire).

Source : Python Concurrency Model Comparison (Medium, 2025)


8. Benchmark : uvloop -- plus rapide que Go et Node.js

uvloop est un remplacement direct de la boucle d'evenements asyncio standard, ecrit en Cython au-dessus de libuv (la meme bibliotheque sous-jacente a Node.js).

Serveur echo TCP :

Implementation1 Kio (req/s)Debit 100 Kio
uvloop105 4592,3 Gio/s
Go103 264--
asyncio standard41 420--
Node.js44 055--

Serveur HTTP (300 concurrents) :

Implementation1 Kio (req/s)
uvloop + httptools37 866
Node.jsInferieur

uvloop : 2,5x plus rapide que l'asyncio standard, 2x plus rapide que Node.js, au niveau de Go.

Source : uvloop: Blazing fast Python networking (MagicStack)


9. Benchmark : aiohttp vs requests -- 10x sur les requetes concurrentes

Bibliothequereq/s (concurrent)Type
aiohttp241+Async
HTTPX (async)~160Async
Requests~24Sync

aiohttp : 10x plus rapide que Requests pour les requetes HTTP concurrentes.

Source : HTTPX vs Requests vs AIOHTTP (Oxylabs)


10. Contre-argument : Cal Paterson -- "Le Python async n'est pas plus rapide"

Il est important de presenter egalement les contre-arguments. Cal Paterson a realise un benchmark approfondi avec une vraie base de donnees (PostgreSQL, selection aleatoire de lignes + JSON) :

FrameworkTypereq/sLatence P99
Gunicorn + Meinheld/BottleSync5 78032 ms
Gunicorn + Meinheld/FalconSync5 58931 ms
Uvicorn + StarletteAsync4 95275 ms
SanicAsync4 68785 ms
AIOHTTPAsync4 50176 ms

Resultat : les frameworks synchrones avec des serveurs en C ont montre un debit superieur et une latence de queue 2-3x meilleure (P99).

Pourquoi l'async a-t-il perdu ?

Raisons :

  1. Une seule requete SQL par requete HTTP -- trop peu d'E/S pour que la concurrence des coroutines ait un effet.
  2. Le multitache cooperatif avec du travail CPU entre les requetes cree une distribution "inegale" du temps CPU -- les calculs longs bloquent la boucle d'evenements pour tout le monde.
  3. La surcharge d'asyncio (boucle d'evenements standard en Python) est comparable au gain de l'E/S non-bloquante lorsque les E/S sont minimales.

Quand l'async aide reellement

Le benchmark de Paterson teste le scenario le plus simple (1 requete SQL). Comme le demontrent les cas de production ci-dessus, l'async apporte un gain spectaculaire quand :

  • Il y a beaucoup de requetes BDD / API externes (Super.com : 40+ appels par requete)
  • La concurrence est elevee (milliers de connexions simultanees)
  • Les E/S dominent par rapport au CPU (Duolingo, Appwrite)

Ceci est conforme a la theorie : plus le coefficient de blocage (T_io/T_cpu) est eleve, plus le benefice des coroutines est grand. Avec 1 requete SQL × 2 ms, le coefficient est trop faible.

Source : Async Python is not faster (Cal Paterson)


11. TechEmpower : frameworks Python

Resultats approximatifs de TechEmpower Round 22 :

FrameworkTypereq/s (JSON)
Uvicorn (brut)Async ASGILe plus eleve en Python
StarletteAsync ASGI~20 000-25 000
FastAPIAsync ASGI~15 000-22 000
Flask (Gunicorn)Sync WSGI~4 000-6 000
Django (Gunicorn)Sync WSGI~2 000-4 000

Frameworks async : 3-5x plus rapides que les synchrones dans le test JSON.

Source : TechEmpower Framework Benchmarks


Resume : ce que montrent les donnees Python

CasSync → AsyncCondition
Duolingo (production)+40% de debit, -30% de coutsMicroservices, E/S
Super.com (production)2x de debit, -90% de couts40+ appels API par requete
Feature Store (production)-40% de latenceMigration des threads vers asyncio
Talk Python (production)-81% de latenceFlask → Quart
I/O-bound (10K URLs)130x plus rapideE/S pure, concurrence massive
aiohttp vs requests10x plus rapideRequetes HTTP concurrentes
uvloop vs standard2,5x plus rapideEcho TCP, HTTP
TechEmpower JSON3-5xFastAPI/Starlette vs Flask/Django
CRUD simple (1 SQL)Le sync est plus rapideCal Paterson : P99 2-3x pire pour async
CPU-boundPas de difference+44% memoire, 0% de gain

Point cle

Le Python async apporte un benefice maximal avec un coefficient de blocage eleve : lorsque le temps d'E/S depasse significativement le temps CPU. Avec 40+ appels reseau (Super.com) -- 90% d'economies de couts. Avec 1 requete SQL (Cal Paterson) -- l'async est plus lent.

Ceci confirme la formule de Efficacite des taches IO-bound : gain ≈ 1 + T_io/T_cpu. Quand T_io >> T_cpu -- des dizaines a des centaines de fois. Quand T_io ≈ T_cpu -- minimal ou nul.


Lien avec PHP et True Async

Python et PHP sont dans une situation similaire :

CaracteristiquePythonPHP
InterpreteOuiOui
GIL / monothreadGILMonothread
Modele dominantSync (Django, Flask)Sync (FPM)
Runtime asyncasyncio + uvloopSwoole / True Async
Framework asyncFastAPI, StarletteHyperf

Les donnees Python montrent que la transition vers les coroutines dans un langage interprete monothread fonctionne. L'echelle du gain est determinee par le profil de charge, pas par le langage.


References

Cas de production

Benchmarks

Coroutines vs threads