В 2018 году Python укрепил свои позиции популярности среди программистов и вошел в Top 3 самых популярных языков на github. Все больше и больше людей переходит на светлую сторону…то есть Python. Появилось еще большее количество разработчиков, которые интересуются данным языком и ведут разработку своих проектов с его помощью. Одним из популярных направлений для Python является web-разработка. Хочется, чтобы не только процесс разработки был удобным и быстрым, но и сами проекты могли похвастаться скоростью и стабильностью работы.

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

Поэтому мы решили составить сравнительный анализ популярных фреймворков, которые не потеряют, мы надеемся, своей актуальности на протяжении всего 2019 года и определить самый быстрый из них.

Участники тестирования


Django




Версия: 2.1.4
Описание: самый популярный комбайн для Python, который из коробки решает множество проблем (админка, авторизация, логирование, ORM, и т.д). Это упрощает жизнь разработчика, но если мы ставим в приоритет скорость работы — то иногда такой комбайн играет против нас и это сказывается на производительности. По этой причине номинацию Fastest Python Web Framework in 2019 он скорее всего не возьмет.

Flask




Версия: 1.0.2
Описание: самый популярный фреймворк на Python (по звездам в GitHub обгоняет даже Django). Популярный выбор в случаях разработки мелких проектов, для которых не нужны те плюшки, которые есть в Django. Позволяет быстро развернуть приложение. Возможно быстрее чем Django по скорости работы, но имеет очень маленькую функциональность “из коробки”.

AioHTTP




Версия: 3.5.1
Описание: очень привлекательный асинхронный Python Framework. Имеет версию клиента и сервера, что значительно развязывает руки при разработке. Обладает очень удобными асинхронными запросами с версии клиента, а также очень хорошие показатели скорости работы сервера при большом количество запросов. Точно должен попасть в тройку лидеров.

Sanic




Версия: 18.12
Описание: можно сказать, что это “многопоточный Flask” со всеми вытекающими. По этой причине мы думаем, что результаты должны быть очень хороши.

Tornado




Версия: 5.1.1
Описание: асинхронный ветеран Python движения, задавший тренд асинхронности в 2010 году. Не теряет своей актуальности и получил 5ю версию в 2018 году. Достаточно высокий порог входа для новичков. Популярен среди олдскульных питонистов, и мы думаем не зря. Должен показать хорошие результаты.

Vibora




Тестируемая версия: релизов на GitHub нет
Описание: многообещающий фреймворк, появившийся в июне 2018 и за последнии полгода набравший более 4000 звезд. Имеет впечатляющие замеры производительности в GitHub. Мы думали именно Vibora станет фаворитом нашей гонки, но к сожалению из-за отсутствия возможности запуска под Python >=3.7 и отсутствия стабильной версии фреймворка мы исключили Vibora.
В GitHub разработчики обещают “кардинально новый” Vibora уже скоро. Посмотрим, что у них получится и обязательно напишем об этом.

Методика тестирования


Тестирование проводилось на Apple iMac 27'' Retina 5K 2017, CPU: 3.5GHz i5, RAM: 8GB, 1000GB Fusion Drive, OSX 10.14.2 при помощи утилиты WRK:

wrk -t12 -c400 -d30s http://127.0.0.1:8080/db/

Тесты проводились на Python 3.7.2. Все фреймворки запускались при помощи Gunicorn с двумя воркерами. Возможно в каких-то случаях использование uwsgi сказалось бы на результатах, но так как мы поставили цель тестировать фреймворки, а не способы их запуска — решили этим пренебречь.

У нас был всего один вид тестов: DB Test, в котором мы получаем строковые данные из базы данных и возвращаем их в виде html-ответа (1 запись в 79 bytes). В качестве базы данных использовался Postgres 11. В качестве драйвера обращений к базе использовался psycopg2 в случае синхронных фреймворков и asyncpg в случае асинхронных.

В качестве event loop библиотеки для асинхронных фреймворков решили использовать uvloop.

Результаты


Запросов в секунду



Вполне ожидаемые лидирующие позиции aiohttp и Sanic, но неожиданные результаты от Tornado.

Передача данных в секунду (Кб)



По количеству переданных данных в секунду Django сильно отстает.

Среднее время запроса (мс)



Снова неприятно удивляет Tornado, на который мы изначально делали ставку. Впечатляет Flask, который по среднему времени запроса конкурирует с потенциальными лидерами.

Максимальное время запроса (сек)



Все “подопытные” показали практически одинаковые результаты по максимальному времени запроса. Все, как мы и ожидали.

Финальные результаты


12 threads


400 connections


Avg Max Requests/sec Transfer/sec (KB)
Latency (ms) Req/Sec Latency (ms) Req/Sec
Django 147,99 120,91 1,98 640 425,71 78,99
Flask 186,8 65,65 1,75 280 546,2 127,48
aiohttp 165,07 247,16 1,98 585 1966,28 439,72
Sanic 194,8 170,85 1,98 470 1520,9 292,6
Tornado 279,3 101,71 1,74 272 778,75 222,07

Итоги


Aiohttp: лидер по производительности на начало 2019 года. Если ваша задача требует ультимативной производительности — то стоит к нему присмотреться. К тому же можно поэкспериментировать с параметрами запуска aiohttp, чтобы выжать из него еще больше. Имеет версию клиента, что позволяет без дополнительных библиотек делать асинхронные запросы. Поэтому для реализации своего нового высоконагруженного сервиса мы выбрали его.

Sanic: популярность фреймворка идет впереди его производительности. Чуда не случилось и обогнать лидера не вышло. В совокупности с тредом на Reddit о проблемах c безопасностью — мы бы не стали использовать Sanic прямо сейчас и подождали действий от разработчиков.

Tornado: “разочарование года”. В связи с результатами — не думаем, что Tornado стоит выбирать для реализации каких-либо новых проектов. Надеемся разработчики что-нибудь придумают и исправят ситуацию.

Django показал ожидаемый результат. Мы любим Django за его возможности и избавление нас от рутины, а не за скорость работы. Обширное community, большое количество материалов в Сети, большое количество реализованных проектов в открытом доступе — все это делает его привлекательным для новичков. Если бы у нас стояла задача быстро разработать MVP типичного web-сервиса — мы бы выбрали в 2019 именно его.

Flask тоже показал ожидаемый результат. Обошел Django за счет того, что имеет не такой богатый функционал из коробки. Не дотянул до скорости асинхронных фреймворков. Мы бы выбрали его в 2019 для реализации небольших pet-проектов или тогда, когда уже важна скорость, но разбираться с асинхронными фреймворками желания еще нет.

Все исходные файлы бенчмарков вы можете посмотреть в репозитории Python Frameworks Benchmark.

Комментарии (21)


  1. SirEdvin
    14.02.2019 13:22

    А как же Starlette?


    1. Jl3oHAPDo Автор
      14.02.2019 13:35

      Я думаю это лучше уточнить у ребят, которые делали бенчмарк.

      Но если интересно мое мнение: то судя по статье они старались тестировать стабильные версии фреймворков, а Starlette еще не релизная. Но могу ошибаться


    1. MikeLP
      14.02.2019 13:57

      Спасибо за ссылку. Жаль пока нет поддержки HTTP2.


      1. gto
        14.02.2019 18:46

        Какие он даст приемущества фреймворку?


        1. MikeLP
          15.02.2019 08:29

          В смысле фреймворку? Это дает преимущество людям которые его используют.


          1. gto
            15.02.2019 11:01

            А не смогут люди воспользовать преимуществами http2 поставив проксирующий веб сервер? Оно и в плане горизонтального масштабирования получше.


  1. andreymal
    14.02.2019 13:37

    Не нужно было использовать Gunicorn: в документации того же aiohttp написано, что с Gunicorn он работает медленнее.


    По бенчмаркам без Gunicorn из первых ссылок в гугле Sanic выходит раза в полтора быстрее чем aiohttp


    1. andreymal
      14.02.2019 13:47
      +1

      Кстати, судя по гитхабу, оно всё ещё и в Docker запускается. Я не специалист, но много начитался про тормознутую сеть в докере и осмелюсь предположить, что это тоже может значительно влиять на результаты


    1. andreymal
      15.02.2019 17:34

      В общем, попробовал сам запустить aiohttp и sanic без gunicorn. У aiohttp ничего принципиально не изменилось, а вот sanic стал в полтора раза быстрее и в итоге в 1.3 раза быстрее чем aiohttp


  1. gnomeby
    14.02.2019 13:50
    -1

    Нет теста компилируемого фреймворка Falcon — статья бессмысленна.
    Согласно их тестам и Django и Flask уделываются в десятки раз, а значит и ваш фаворит скорее всего прогнётся.


    1. iroln
      15.02.2019 12:57

      Что значит "компилируемого"? Там просто все файлы транслируются в C-экстеншены с помощью cython. "Ситонизация" обычного питоновского кода почти не прибавляет к производительности такого кода. А чисто ситоновского оптимизированного кода там нет. Поэтому они и пишут, что:


              print('\nNOTE: Cython not installed. '
                    'Falcon will still work fine, but may run '
                    'a bit slower.\n')

      "a bit slower"


      1. gnomeby
        15.02.2019 13:01

        А по тестам Falcon команды прирост производительности в 1.5 раза.


        1. iroln
          15.02.2019 13:07

          Это и есть "a bit faster" :)
          Если бы они переписали код на чистом cython (pyx/pxd), производительность могла бы увеличиться в десятки раз (это, строго говоря, верно для какого-то вычислительного кода на питоне, потому как в случае web-фреймворка всё конечно сложнее). Но именно ситонизация py-кода даёт очень незначительный прирост так как выполняется тупая трансляция в CPython API со всем динамизмом, тогда как код на cython уже статически строго типизирован.


          1. gnomeby
            15.02.2019 13:10

            Вы можете называть это хоть a little bit faster, это всего-лишь слова. А в реальности на выходе мы имеет веб-приложение обрабатывающее в 1.5 раза больше запросов и это офигенно.


  1. Hardcoin
    14.02.2019 13:55
    +1

    Но ведь aiohttp не фреймворк для разработки сайтов (в отличии от Django). Мне сравнение больше напоминает подводную лодку против карьерного самосвала. Сравнить можно, но имеет ли оно смысл?


  1. Cykooz
    14.02.2019 18:23

    По моему тут опять сравнили мягкое с пушистым. Как можно сравнивать скорость работы по числу запросов в секунду, если сравнивается всего ДВА воркера для синхронных фреймворков с условно бесконечным числом «воркеров» для асинхронных?
    В таком тесте корректнее сравнивать время на обработку одного запроса. По этому показателю в этом тесте победил Django.
    А если хочется сравнить число запросов в секунду, то надо значительно увеличить число воркеров для синхронных фреймворков. И заодно собрать статистику как от числа воркеров зависит число запросов в секунду и объём потребляемой памяти.


    1. SirEdvin
      14.02.2019 18:51

      условно бесконечным числом «воркеров» для асинхронных?

      Вы же понимаете, что, если скажем, запрос в бд будет выполнятся очень быстро, то синхронные окажутся быстрее, потому что в асинке есть, например, оверхед на переключения.


  1. vlviking
    15.02.2019 12:13

    Торнадо разочаровал.


  1. andreymal
    15.02.2019 14:36

    Docker
    OSX
    Так стоп, я правильно понимаю, что это всё ещё и в VirtualBox запускалось?


    1. andreymal
      15.02.2019 15:15

      Почитал матчасть — ну или HyperKit, что, впрочем, не лучше


  1. poweruser
    16.02.2019 01:19

    Bottle кто-то использует в наше время?