На диаграммах ниже приведены результаты простейшего Apache Benchmarka для фреймворков Django версии 3.1, Flask 1.1 и AIOHTTP 3.7. AIOHTTP работает в штатном однопоточном асинхронном режиме, Django и Flask обслуживаются синхронным WSGI сервером Gunicorn с числом потоков, равным числу доступных ядер процессора * 2. ASGI в тесте не участвовал.
SELECT r.id, r.auth_user_id, r.status, r.updated, r.label, r.content, u.username, ARRAY_AGG(t.tag) tag, COUNT(*) OVER() cnt, ( SELECT COUNT(*) FROM record r2 WHERE r2.parent_id IS NOT NULL AND r2.parent_id = r.id AND r2.status = 'new' ) AS partsFROM record rJOIN auth_user u ON u.id = r.auth_user_idLEFT JOIN tag t ON t.kind_id = r.id AND t.kind = 'rec'WHERE r.parent_id IS NULL AND r.status = 'new'GROUP BY r.id, u.usernameORDER BY r.updated DESCLIMIT 10 OFFSET 0
Этот запрос получает список корневых записей из основной таблицы приложения, число прямых потомков для каждой строки, данные владельца записи, список тегов и общее число строк выборки.
AIOHTTP использует пулл соединений с БД и драйвер asyncpg, Django и Flask SQLAlchemy без ORM (для чистоты эксперимента) и psycopg2.
Приложение Django создано стандартными средствами фреймворка (django-admin startproject, manage.py startapp и т.д.), вывод тестовой страницы через ListView. Установки Flask и AIOHTTP построены на канонических веб приложениях Hello, world, взятых из документации.
Результаты запуска теста на локальной машине (4 ядра CPU)
и на реальном однопроцессорном VDS (пинг около 45 ms)
Во время теста AIOHTTP использовал 100% одного ядра CPU, Flask и Django 100% всех доступных ядер.
Выводы
На самом деле, сравнение асинхронных и многопоточных приложений не совсем корректно они решают разные задачи. Поэтому, результат выглядит довольно логичным: в локальном тесте у AIOHTTP просто оказалось меньше ресурсов, при равных условиях производительность нивелируется.
А вот скромный результат Flaskа с трудом поддается объяснению, разогнать этот фреймворк у меня не получилось.