Pull to refresh

Comments 9

Про select рассказал, думал сейчас пойдем в epoll, kqueue, io_uring. Отличное введение.

Системные вызовы для мультиплексирования ввода/вывода оставил на следующую часть)

Python не самый подходящий язык для написания производительного веб-сервера. Хорошая база для понимания, но как сказал оратор выше - без io_uring будет шляпа. Я в свое время тоже пилил свой веб сервер, но потом бросил это дело, ибо реализация ssl и gzip требует годы(в моем случае). Научился только работать с CGI/FCGI. На тестах wrk получил следующее:
wrk -t8 -c1000 -d10s http://127.0.0.1:8080Running 10s test @ http://127.0.0.1:8080  8 threads and 1000 connections  Thread Stats Avg Stdev Max +/- Stdev    Latency 3.30ms 5.07ms 23.33ms 81.93%    Req/Sec 102.38k 7.81k 114.90k 89.25%  8147678 requests in 10.03s, 4.17GB readRequests/sec: 812518.83Transfer/sec: 426.18MB

Дальше руки опустились)

Да, цель статьи именно дать базу для понимания. В целом в экосистеме Python в основном и используются asgi-сервера на Python, правда цикл событий обычно uvloop, а там уже Cython и libuv. Но i/o мультиплексируется за счёт epoll, и насколько я знаю, не он является узким местом. Последнее время есть ещё интересные движения в сторону rsgi-серверов на Rust, но в проде ещё не использовал - хватает и текущей производительности, и узкое место не в сервере. Но для веб-серверов общего назначения вроде nginx Python конечно не подойдёт.

812к rps впечатляет, на каком языке писали?

nasm syscall only + всяческие оптимизации. Был амбициозный проект, который вынул из меня душу, в итоге отложил его в очень долгий ящик.

Последнее время есть ещё интересные движения в сторону rsgi-серверов на Rust

Вот результаты тестов wrk на реальном железе:
https://www.techempower.com/benchmarks/#section=test&runid=1d5bfc8a-5c4a-4fb2-a792-ad967f1eb138&test=json&l=zik0zj-pa6


RSGI даёт выигрыш только в самом granian.
Но если использовать очень быстрый ASGI сервер FastPySGI (это форк FastWSGI), то никакого преимущества от RSGI мы не получим.
Вот я как раз на днях зарелизнул в PyPI свежий FastPySGI.

самая большая проблема те кто пытается работать с Python, это не знание самого языка и как он работает под капотом! в данном языке это сверх важно для успеха!
я тестировал сам это все со знаниями Python не синтаксиса, а хорошим пониманием как он работает. как итог вышло так:
36к запросов на 2 потока (воркера), 0 ошибок, 0.6 сек задержка в среднем, 100 одновременных в сек.

понимание как работают воркеры, как работают сокеты и работа с сетью под капотом, очень важно в Python! так же важно понимание как он работает с памятью.
на одно ядро можно повесить много воркеров. НО! надо занижать одновременное обращение на воркер, ибо GIL... если не занизить толку не будет, потеряете скорость как итог..
это не Си подобный язык! и многие путают работу Си подобных с Python, вот у них и получается абы что.. вроде делают все верно, а на деле ерунда..

у меня по итогу тестов получилось разогнать Python Flask на одном ядре до 50к+ запросов в секунду при RPS 98... это очень много, и можно больше если более глубоко разобраться в самом Python.

50к это очень и очень много! если для вас это мало на одном ядре, то я не знаю что вы там делать собрались.. в 99% вы упретесь на 15к в базу.. после 15к уже будет борьба за обращение базу, часто раньше.

в Python очень сложно писать что-то хорошее, потому что надо глубокие знания языка и не только его. но легко изучать само программирование. не путайте простоту Python с его не пригодностью! он был медленный на 2.7 версии. уже давно 3.14 которая в сотни, если не в тысячи раз быстрее. учитесь программировать а не писать код, который легко генерирует LLM..

я написал как получить результат. еще есть разные сервера под разные задачи, в Flasck тоже их несколько и все они под разные задачи! даже асинхронных несколько! основной который часто используют не совсем про асинхронность, там есть прекрасный сервер для асинхронной работы синхронного Flask.
вроде про все сказал, дальше сами учите, ищите, изучайте кому оно интересно. есть еще две превосходные книги на эти темы, даже три. и все у вас получиться!
одно из книг "сетевое программирование на Python". могу ошибиться в названии. вторая чисто на английском есть.. третья "AsyncIO и конкурентное программирование на Python", тут важно не перепутать конкурентное с многопоточным и разбиение на процессы.. на инглише точно названия не помню.. вспомню свернусь напишу.

сокеты в Linux особенно Ubuntu могут работать с задержками если их не настроить!

PS.
За статью спасибо!
С уважением!

как итог вышло так:36к запросов на 2 потока (воркера), 0 ошибок, 0.6 сек задержка в среднем, 100 одновременных в сек.

у меня по итогу тестов получилось разогнать Python Flask на одном ядре до 50к+ запросов в секунду при RPS 98... это очень много

А почему без Flask всего 36к, а с оным - 50к+ ?
50к+ через Flask на 1 воркере ну никак не получить (pypy не считается). Либо как-то неправильно проводился тест.

Вот тут представлено сравнение "скорости" чистого Flask (на самом деле через werkzeug) и фласков с бустом в виде сторонних WSGI-серверов:
https://github.com/jamesroberts/fastwsgi/blob/main/performance_benchmarks/PERFORMANCE.md#requests-per-second-1
Я сейчас провёл тест на свежем Flask 3.1.3 и вот что вышло.
1) Flask + werkzeug

> ./wrk -t8 -c100 -d10s http://127.0.0.1:5000/hw
Running 10s test @ http://127.0.0.1:5000/hw
  8 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    28.94ms    0.85ms  32.04ms   96.47%
    Req/Sec   415.43     50.91   484.00     35.75%
  33108 requests in 10.01s, 5.84MB read
Requests/sec:   3308.02
Transfer/sec:    597.64KB

2) Flask + FastWSGI

> ./wrk -t8 -c100 -d10s http://127.0.0.1:5000/hw
Running 10s test @ http://127.0.0.1:5000/hw
  8 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     9.94ms  575.16us  19.17ms   97.64%
    Req/Sec     1.21k    40.10     1.33k    80.38%
  96582 requests in 10.01s, 16.21MB read
Requests/sec:   9652.05
Transfer/sec:      1.62MB

3) Чистый FastWSGI (FastPySGI):

> ./wrk -t8 -c100 -d10s http://127.0.0.1:5000/hw
Running 10s test @ http://127.0.0.1:5000/hw
  8 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   736.81us   71.25us   6.70ms   92.91%
    Req/Sec    16.34k   788.94    19.81k    81.41%
  1312189 requests in 10.10s, 202.73MB read
Requests/sec: 129925.07
Transfer/sec:     20.07MB

Во всех тестах используется 1 воркер (python 3.9)


Sign up to leave a comment.

Articles