Найти плагин cpu-hogging в многопоточном питоне - PullRequest
8 голосов
/ 23 июня 2009

У меня есть система, написанная на python, которая обрабатывает большие объемы данных с помощью плагинов, написанных несколькими разработчиками с различным уровнем опыта.

По сути, приложение запускает несколько рабочих потоков, а затем передает им данные. Каждый поток определяет плагин, который будет использоваться для элемента, и просит его обработать элемент. Плагин - это просто модуль Python с определенной определенной функцией. Обработка обычно включает регулярные выражения и не должна занимать более секунды или около того.

Время от времени одному из плагинов требуется минут для завершения, привязывая ЦП к 100% за все время. Обычно это вызвано неоптимальным регулярным выражением в паре с элементом данных, который демонстрирует эту неэффективность.

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

  • Я не могу быть однопоточным. Вероятно, потребуется недели , чтобы воспроизвести проблему, если я это сделаю.
  • Установка таймера на плагине не помогает, потому что, когда он зависает, он забирает GIL, а все остальные плагины также требуют минут.
  • (Если вам интересно, двигатель SRE не выпускает GIL ).
  • Насколько я могу судить профилирование довольно бесполезно при многопоточности.

Если не считать переписывания всей архитектуры в многопроцессорную, каким-либо образом я могу узнать, кто потребляет весь мой процессор?

ДОБАВЛЕНО : В ответ на некоторые комментарии:

  1. Профилирование многопоточного кода в python бесполезно, поскольку профилировщик измеряет общее время функции, а не время активного процессора. Попробуйте cProfile.run ('time.sleep (3)'), чтобы понять, что я имею в виду. (кредит rog [последний комментарий]).

  2. Причина, по которой однопотоковое использование является хитрым, заключается в том, что только 1 элемент из 20 000 вызывает проблему, и я не знаю, какой именно. Запуск многопоточности позволяет мне проходить 20000 элементов примерно за час, в то время как однопоточность может занимать гораздо больше времени (в этом участвует большая задержка сети). Есть еще несколько сложностей, с которыми я бы не хотел сейчас сталкиваться.

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

Ответы [ 4 ]

3 голосов
/ 23 июня 2009

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

Попробуйте многопроцессорную обработку вместо многопоточности

Однопоточность / N подпроцессов. Там вы можете определить время каждого запроса, поскольку GIL не удерживается.

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

0 голосов
/ 24 июня 2009

Я бы еще посмотрел на предложение Носкло. Вы можете создать профиль в единственном потоке, чтобы найти предмет, и получить дамп при очень долгой пробежке и, возможно, увидеть виновника. Да, я знаю, что это 20 000 предметов, и на это уйдет много времени, но иногда нужно просто смириться с этим и найти проклятую вещь, чтобы убедить себя, что проблема поймана и решена. Запустите скрипт и приступайте к работе над чем-то еще конструктивным. Вернись и проанализируй результаты. Это то, что иногда отделяет мужчин от мальчиков; -)

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

0 голосов
/ 23 июня 2009

Если бы предложили, так как у вас есть контроль над фреймворком, отключите все, кроме одного плагина, и посмотрите. В основном, если у вас есть плагины P1, P2 ... Pn запустить процесс N и отключить P1 в первую очередь, P2 во вторую и т. д.

это будет намного быстрее по сравнению с многопоточным прогоном, так как нет блокировки GIL, и вы быстрее узнаете, какой плагин является виновником.

0 голосов
/ 23 июня 2009

Как вы сказали, из-за GIL это невозможно в рамках одного и того же процесса.

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

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