У меня есть система, написанная на python, которая обрабатывает большие объемы данных с помощью плагинов, написанных несколькими разработчиками с различным уровнем опыта.
По сути, приложение запускает несколько рабочих потоков, а затем передает им данные. Каждый поток определяет плагин, который будет использоваться для элемента, и просит его обработать элемент. Плагин - это просто модуль Python с определенной определенной функцией. Обработка обычно включает регулярные выражения и не должна занимать более секунды или около того.
Время от времени одному из плагинов требуется минут для завершения, привязывая ЦП к 100% за все время. Обычно это вызвано неоптимальным регулярным выражением в паре с элементом данных, который демонстрирует эту неэффективность.
Здесь все становится сложнее. Если у меня есть подозрение, кто виноват, я могу проверить его код и найти проблему. Впрочем, иногда мне не так везет.
- Я не могу быть однопоточным. Вероятно, потребуется недели , чтобы воспроизвести проблему, если я это сделаю.
- Установка таймера на плагине не помогает, потому что, когда он зависает, он забирает GIL, а все остальные плагины также требуют минут.
- (Если вам интересно, двигатель SRE не выпускает GIL ).
- Насколько я могу судить профилирование довольно бесполезно при многопоточности.
Если не считать переписывания всей архитектуры в многопроцессорную, каким-либо образом я могу узнать, кто потребляет весь мой процессор?
ДОБАВЛЕНО : В ответ на некоторые комментарии:
Профилирование многопоточного кода в python бесполезно, поскольку профилировщик измеряет общее время функции, а не время активного процессора. Попробуйте cProfile.run ('time.sleep (3)'), чтобы понять, что я имею в виду. (кредит rog [последний комментарий]).
Причина, по которой однопотоковое использование является хитрым, заключается в том, что только 1 элемент из 20 000 вызывает проблему, и я не знаю, какой именно. Запуск многопоточности позволяет мне проходить 20000 элементов примерно за час, в то время как однопоточность может занимать гораздо больше времени (в этом участвует большая задержка сети). Есть еще несколько сложностей, с которыми я бы не хотел сейчас сталкиваться.
Тем не менее, неплохо было бы попытаться сериализовать конкретный код, который вызывает плагины, чтобы синхронизация одного не влияла на синхронизацию других. Я попробую это и доложу.