Python asyncio на практиці: реальні вимірювання

Python — мова, найбільш схожа на PHP за моделлю виконання: інтерпретована, однопотокова (GIL), з домінуванням синхронних фреймворків. Перехід від синхронного Python (Flask, Django + Gunicorn) до асинхронного (FastAPI, aiohttp, Starlette + Uvicorn) — це точна аналогія переходу від PHP-FPM до корутинного середовища виконання.

Нижче наведено збірку продакшн-кейсів, незалежних бенчмарків та вимірювань.


1. Продакшн: Duolingo — міграція на Async Python (+40% пропускної здатності)

Duolingo — найбільша платформа для вивчення мов (500M+ користувачів). Бекенд написаний на Python.

У 2025 році команда розпочала систематичну міграцію сервісів із синхронного Python на асинхронний.

МетрикаРезультат
Пропускна здатність на інстанс+40%
Економія на AWS EC2~30% на мігрований сервіс

Автори зазначають, що після побудови асинхронної інфраструктури міграція окремих сервісів виявилася «досить простою».

Джерело: How We Started Our Async Python Migration (Duolingo Blog, 2025)


2. Продакшн: Super.com — зниження витрат на 90%

Super.com (раніше Snaptravel) — сервіс пошуку готелів та знижок. Їхній пошуковий рушій обробляє 1 000+ req/s, приймає 1 ТБ+ даних на день та обробляє $1M+ продажів щодня.

Ключова характеристика навантаження: кожен запит виконує 40+ мережевих викликів до сторонніх API. Це чистий I/O-bound профіль — ідеальний кандидат для корутин.

Команда мігрувала з Flask (синхронний, AWS Lambda) на Quart (ASGI, EC2).

МетрикаFlask (Lambda)Quart (ASGI)Зміна
Витрати на інфраструктуру~$1,000/день~$50/день−90%
Пропускна здатність~150 req/s300+ req/s2x
Помилки у пікові годиниБазовий рівень−95%−95%
ЗатримкаБазовий рівень−50%2x швидше

Економія $950/день × 365 = ~$350 000/рік на одному сервісі.

Джерело: How we optimized service performance using Quart ASGI and reduced costs by 90% (Super.com, Medium)


3. Продакшн: Instagram — asyncio на масштабі 500M DAU

Instagram обслуговує 500+ мільйонів щоденних активних користувачів на бекенді Django.

Jimmy Lai (інженер Instagram) описав міграцію на asyncio у доповіді на PyCon Taiwan 2018:

  • Замінили requests на aiohttp для HTTP-викликів
  • Мігрували внутрішній RPC на asyncio
  • Досягли покращення продуктивності API та зменшення простою CPU

Виклики: високе навантаження asyncio на CPU на масштабі Instagram, необхідність автоматизованого виявлення блокуючих викликів через статичний аналіз коду.

Джерело: The journey of asyncio adoption in Instagram (PyCon Taiwan 2018)


4. Продакшн: Feature Store — від потоків до asyncio (−40% затримки)

Сервіс Feature Store мігрував з багатопоточності Python на asyncio.

МетрикаПотокиAsyncioЗміна
ЗатримкаБазовий рівень−40%−40%
Споживання RAM18 ГБ (сотні потоків)Значно меншеСуттєве зменшення

Міграція виконувалася у три фази з розподілом продакшн-трафіку 50/50 для валідації.

Джерело: How We Migrated from Python Multithreading to Asyncio (Medium)


5. Продакшн: Talk Python — Flask до Quart (−81% затримки)

Talk Python — один з найбільших подкастів та навчальних платформ Python. Автор (Michael Kennedy) переписав сайт з Flask (синхронний) на Quart (асинхронний Flask).

МетрикаFlaskQuartЗміна
Час відповіді (приклад)42 мс8 мс−81%
Помилки після міграції2Мінімально

Автор зазначає: під час навантажувального тестування максимальний req/s відрізнявся несуттєво, оскільки запити до MongoDB займали <1 мс. Виграш проявляється при одночасній обробці запитів — коли кілька клієнтів звертаються до сервера одночасно.

Джерело: Talk Python rewritten in Quart (async Flask)


6. Microsoft Azure Functions — uvloop як стандарт

Microsoft включив uvloop — швидкий цикл подій на базі libuv — як стандартний для Azure Functions на Python 3.13+.

ТестСтандартний asynciouvloopПокращення
10K запитів, 50 VU (локально)515 req/s565 req/s+10%
5 хв, 100 VU (Azure)1 898 req/s1 961 req/s+3%
500 VU (локально)720 req/s772 req/s+7%

Стандартний цикл подій при 500 VU показав ~2% втрат запитів. uvloop — нуль помилок.

Джерело: Faster Python on Azure Functions with uvloop (Microsoft, 2025)


7. Бенчмарк: I/O-bound задачі — asyncio у 130 разів швидше

Пряме порівняння моделей конкурентності на задачі завантаження 10 000 URL:

МодельЧасПропускна здатністьПомилки
Синхронна~1 800 с~11 КБ/с
Потоки (100)~85 с~238 КБ/сНизький
Asyncio14 с1 435 КБ/с0,06%

Asyncio: у 130 разів швидше за синхронний код, у 6 разів швидше за потоки.

Для CPU-bound задач asyncio не дає переваг (ідентичний час, +44% споживання пам'яті).

Джерело: Python Concurrency Model Comparison (Medium, 2025)


8. Бенчмарк: uvloop — швидше за Go та Node.js

uvloop — це заміна стандартного циклу подій asyncio, написана на Cython поверх libuv (тієї ж бібліотеки, що лежить в основі Node.js).

TCP echo-сервер:

Реалізація1 KiB (req/s)100 KiB пропускна здатність
uvloop105 4592,3 ГіБ/с
Go103 264
Стандартний asyncio41 420
Node.js44 055

HTTP-сервер (300 одночасних підключень):

Реалізація1 KiB (req/s)
uvloop + httptools37 866
Node.jsНижче

uvloop: у 2,5 рази швидше за стандартний asyncio, у 2 рази швидше за Node.js, на рівні з Go.

Джерело: uvloop: Blazing fast Python networking (MagicStack)


9. Бенчмарк: aiohttp проти requests — 10x на одночасних запитах

Бібліотекаreq/s (одночасних)Тип
aiohttp241+Async
HTTPX (async)~160Async
Requests~24Sync

aiohttp: у 10 разів швидше за Requests для одночасних HTTP-запитів.

Джерело: HTTPX vs Requests vs AIOHTTP (Oxylabs)


10. Контраргумент: Cal Paterson — «Async Python не швидший»

Важливо навести й контраргументи. Cal Paterson провів ретельний бенчмарк з реальною базою даних (PostgreSQL, випадковий вибір рядка + JSON):

ФреймворкТипreq/sP99 затримка
Gunicorn + Meinheld/BottleSync5 78032 мс
Gunicorn + Meinheld/FalconSync5 58931 мс
Uvicorn + StarletteAsync4 95275 мс
SanicAsync4 68785 мс
AIOHTTPAsync4 50176 мс

Результат: синхронні фреймворки з C-серверами показали вищу пропускну здатність та у 2–3 рази кращу хвостову затримку (P99).

Чому async програв?

Причини:

  1. Один SQL-запит на HTTP-запит — занадто мало I/O, щоб конкурентність корутин мала ефект.
  2. Кооперативна багатозадачність із CPU-роботою між запитами створює «нечесний» розподіл процесорного часу — довгі обчислення блокують цикл подій для всіх.
  3. Накладні витрати asyncio (стандартний цикл подій у Python) порівнянні з виграшем від неблокуючого I/O, коли I/O мінімальний.

Коли async справді допомагає

Бенчмарк Paterson тестує найпростіший сценарій (1 SQL-запит). Як демонструють продакшн-кейси вище, async дає драматичний виграш, коли:

  • Є багато запитів до БД / зовнішніх API (Super.com: 40+ викликів на запит)
  • Конкурентність висока (тисячі одночасних з'єднань)
  • I/O домінує над CPU (Duolingo, Appwrite)

Це узгоджується з теорією: чим вищий коефіцієнт блокування (T_io/T_cpu), тим більший виграш від корутин. При 1 SQL-запиті × 2 мс коефіцієнт занадто низький.

Джерело: Async Python is not faster (Cal Paterson)


11. TechEmpower: фреймворки Python

Приблизні результати з TechEmpower Round 22:

ФреймворкТипreq/s (JSON)
Uvicorn (raw)Async ASGIНайвищий серед 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

Асинхронні фреймворки: у 3–5 разів швидше за синхронні у JSON-тесті.

Джерело: TechEmpower Framework Benchmarks


Підсумок: що показують дані Python

КейсSync → AsyncУмова
Duolingo (продакшн)+40% пропускної здатності, −30% витратМікросервіси, I/O
Super.com (продакшн)2x пропускної здатності, −90% витрат40+ API-викликів на запит
Feature Store (продакшн)−40% затримкиМіграція з потоків на asyncio
Talk Python (продакшн)−81% затримкиFlask → Quart
I/O-bound (10K URL)130x швидшеЧистий I/O, масова конкурентність
aiohttp проти requests10x швидшеОдночасні HTTP-запити
uvloop проти стандартного2,5x швидшеTCP echo, HTTP
TechEmpower JSON3–5xFastAPI/Starlette проти Flask/Django
Простий CRUD (1 SQL)Sync швидшеCal Paterson: P99 у 2–3 рази гірше для async
CPU-boundБез різниці+44% пам'яті, 0% виграшу

Ключовий висновок

Async Python дає максимальну користь при високому коефіцієнті блокування: коли час I/O значно перевищує час CPU. При 40+ мережевих викликах (Super.com) — 90% економії витрат. При 1 SQL-запиті (Cal Paterson) — async повільніше.

Це підтверджує формулу з Ефективність IO-bound задач: виграш ≈ 1 + T_io/T_cpu. Коли T_io >> T_cpu — десятки та сотні разів. Коли T_io ≈ T_cpu — мінімальний або нульовий.


Зв'язок з PHP та True Async

Python та PHP перебувають у схожій ситуації:

ХарактеристикаPythonPHP
ІнтерпретованаТакТак
GIL / однопотоковаGILОднопотокова
Домінуюча модельSync (Django, Flask)Sync (FPM)
Асинхронне середовищеasyncio + uvloopSwoole / True Async
Асинхронний фреймворкFastAPI, StarletteHyperf

Дані Python показують, що перехід на корутини в однопотоковій інтерпретованій мові працює. Масштаб виграшу визначається профілем навантаження, а не мовою.


Посилання

Продакшн-кейси

Бенчмарки

Корутини проти потоків