Найти - Пользователи
Полная версия: Многопоточные сетевые приложения замедляются после промежутка времени
Начало » Python для экспертов » Многопоточные сетевые приложения замедляются после промежутка времени
1 2 3
Lexander
Ну и посмотрите http://mg.pov.lt/objgraph/ - с ним проще найти утечку.
deye
А в каком случае может не произойти захват лока? Ну кроме случая, когда он захвачен другим потоком.

Насчёт очереди с результатами - спасибо, попробую.

Исходя из кода я все таки спрошу:
Вы уверены в этом?
И что правильно ловятся, с уничтожением объектов?

Если бы все не ловились, то я бы получил их от интерпретатора, так как функция process_task в try/except не обёрнута.
А что значит ловить правильно? Уничтожение объектов вручную не делую (если вы имеете ввиду вызов метода del). Но разве сборщик мусора не должен их убить? Ведь после завершения process_task никаких внешних ссылок не остаётся (кроме самого задания).
Lexander
deye
А в каком случае может не произойти захват лока? Ну кроме случая, когда он захвачен другим потоком.
Именно в этом случае и может.
И ваш последующий код сработает совсем не так, как вы того ожидаете.

deye
Но разве сборщик мусора не должен их убить?
И убьет.
Вопрос в том, когда он это сделает.
Если, например, через 10 минут (условно), то все эти 10 минут у вас накапливаются ссылки и занимают память.

deye
Ведь после завершения process_task никаких внешних ссылок не остаётся
Результат (память растет) противоречит этому предположению ;)
deye
Именно в этом случае и может.
И ваш последующий код сработает совсем не так, как вы того ожидаете.

Видимо я не понимаю как работают локи. Я ожидал такого развития событий:
Если 1 поток захватило лок, то остальные потоки про попытке его захватить заблокируются, до того момента как он освободится. Далее следующий поток захватит его и так далее.
Т.е. кусок кода по записи в файл должен выполняться только одним потоком в один момент времени.
Lexander
Все так, но вы не проверяете захватился ли лок.
И не учитываете инертность файловой системы при операциях с файлами.
reclosedev
А как оценивается скорость работы? Запросы в секунду, еще что-то или вообще субъективно?

Просто, например, если считается общее количество заданий(запросов) и делится на время, то таймауты нескольких запросов сильно попортят значение задания/время.
deye
Lexander, объясните, пожалуйста, что вы имеете ввиду под проверкой лока? Разве попытка захватить лок не есть проверка?

reclosedev, количество заданий в час. Таймауты в 20-30 секунд не особо будут влиять на статистику в таком случае. Тем более влиять практически на 1 порядок, как у меня
deye
Убрал использование локов, сделал очередь с результатами и один поток, который пишет данные из этой очереди -> Не помогло.
Кстати, возможно важную подробность забыл упомянуть: чем больше потоков, тем быстрее наступает время, после которого скорость падает. И время опять же будет всегда примерно одинаковым для одного и того же количества потоков.
Т.е. скажем если 100 потоков - скорость падает через 3 часа,
если 200 потоков - через 2 часа,
300 потоков - через час.
(данные для примера, не фактические)

Насчёт потребляемой памяти: с момента запуска до момента замедления (примерно 20 мин) употребление памяти увеличилось примерно на 5мб. Это серьёзно?
Lexander
deye
Lexander, объясните, пожалуйста, что вы имеете ввиду под проверкой лока?
lock.locked()
deye
Убрал использование локов, сделал очередь с результатами и один поток, который пишет данные из этой очереди -> Не помогло.
Этот совет касался других проблем, которые я описал выше.
deye
Насчёт потребляемой памяти: с момента запуска до момента замедления (примерно 20 мин) употребление памяти увеличилось примерно на 5мб. Это серьёзно?
Нет, это мало.

Сколько вы говорите у вас потоков - 100 и более?
Это может в корне изменить источник проблемы.
Специально пишу - это гипотезу, которую нужно проверить, а то мы уже с памятью начали бороться, хотя по факту, оказывается, ее мало расходуется.
Добавьте в список потенциальных причин GIL и переключения контекста между потоками - вот здесь тратится время.
Чтобы проверить эту гипотезу, проверьте время до замедления с разным количеством потоков.
Если она подтвердится,
либо уменьшить количество потоков - этот вариант подойдет, если сетевой интерфейс нагружен на 50 и более процентов;
либо переписать код на multiprocessing, twisted, asyncore и т.п. вещах

Вообще, любой IO лучше писать на потоках или асинхронно.
Сеть - это тоже IO.

Профилирование с ObjGraph вы все таки проведите, чтобы удостоверится в отсутствии большого количества зависших объектов, которые нужно почистить - на это тоже тратится время.
lorien
Ещё можно попробовать вместо threading заюзать multiprocessing, ну и в любом случае 100 тредов-потоков это не очень прикольно, для этого я и сделал Grab::Spider, чтобы сотни тредов или процессов не создавать.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB