Может ли медленная сеть заставить приложение Python использовать * больше * ЦП? - PullRequest
4 голосов
/ 26 июня 2009

Допустим, у нас есть такая система:

                                                                     ______
                              { application instances ---network--- (______)
                             {  application instances ---network--- |      |
requests ---> load balancer {   application instances ---network--- | data |
                             {  application instances ---network--- | base |
                              { application instances ---network--- \______/

Приходит запрос, балансировщик нагрузки отправляет его экземпляру сервера приложений, а экземпляры сервера приложений связываются с базой данных (в другом месте локальной сети). Экземпляры приложения могут быть отдельными процессами или отдельными потоками. Просто чтобы охватить все базы, скажем, есть несколько идентичных процессов, каждый из которых имеет пул идентичных потоков службы приложений.

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

Теперь, во всем моем опыте, предшествующем Python, это сопровождалось бы соответствующим падением загрузки ЦП приложениями - они бы тратили больше времени на блокировку ввода-вывода и меньше время на выполнение ресурсоемких задач.

Однако мне говорят, что с Python это не так - при определенных обстоятельствах Python эта ситуация может привести к тому, что загрузка процессора Python увеличится на вверх , возможно, до 100% , Что-то в Global Interpreter Lock и нескольких потоках, возможно, заставляет Python тратить все свое время на переключение между потоками, проверяя, есть ли у кого-нибудь из них ответ из базы данных. «Отсюда рост числа однопроцессных управляемых событиями библиотек в последнее время».

Это правильно? Действительно ли потоки службы приложений Python используют больше ЦП, когда их задержка ввода-вывода увеличивается?

Ответы [ 4 ]

6 голосов
/ 26 июня 2009

В теории нет, на практике это возможно; это зависит от того, что вы делаете.

Существует полное часовое видео и pdf об этом , но, по сути, оно сводится к некоторым непредвиденным последствиям GIL с потоками, связанными с ЦП и IO, с многоядерными процессорами. По сути, поток, ожидающий ввода-вывода, должен проснуться, поэтому Python начинает «вытеснять» другие потоки каждый тик Python (вместо каждых 100 тиков). В этом случае поток ввода-вывода испытывает проблемы с извлечением GIL из потока ЦП, что приводит к повторению цикла.

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

Конечно, как говорили другие авторы, это исчезнет, ​​если у каждого будет свой собственный процесс.

По совпадению, слайды и видео объясняют, почему вы иногда не можете использовать CTRL + C в Python.

1 голос
/ 26 июня 2009

Нет, это не тот случай. Хватит распространять ФУД.

Если ваше приложение на Python заблокировано по вызову C API, например. блокируя сокеты или чтение файла, он, вероятно, выпустил GIL.

1 голос
/ 26 июня 2009

Что-то о Global Interpreter Lock и множественных потоках предположительно заставляет Python тратить все свое время на переключение между потоками, проверяя, есть ли у какого-либо из них ответ из базы данных.

Это совершенно безосновательно. Если все потоки заблокированы при вводе / выводе, Python должен использовать 0% CPU. Если есть один незаблокированный поток, он сможет работать без конфликта GIL; он периодически освобождает и повторно запрашивает GIL, но не выполняет никакой работы по «проверке» в других потоках.

Однако в многоядерных системах поток может ждать некоторое время, чтобы повторно запросить GIL, если существует поток, связанный с процессором, и сократить время отклика (см. эту презентацию для подробности). Это не должно быть проблемой для большинства серверов.

1 голос
/ 26 июня 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...