Out of Memory Killer активирован для скрипта python, запускающего многопроцессорную очередь?

Я написал программу на Python, которую нужно запускать несколько дней из-за постоянного сбора данных. Раньше у меня не было проблем с запуском этой программы в течение нескольких месяцев. Недавно я сделал несколько обновлений для программы, и теперь, примерно через 12 часов, я получаю ужасный убийцу памяти. Вывод dmesg следующий:

[9084334.914808] Out of memory: Kill process 2276 (python2.7) score 698 or sacrifice child
[9084334.914811] Killed process 2276 (python2.7) total-vm:13279000kB, anon-rss:4838164kB, file-rss:8kB

Помимо обычного кода на Python, основным изменением, внесенным в программу, стало добавление многопроцессорной очереди. Это первый раз, когда я использовал эту функцию, поэтому я не уверен, что это может быть причиной проблемы. Назначение Очереди в моей программе — возможность вносить динамические изменения в параллельный процесс. Очередь инициируется в основной программе и постоянно отслеживается в параллельном процессе. Упрощенная версия того, как я делаю это в параллельном процессе, выглядит следующим образом (где «q» — это очередь):

while(1):

    if q.empty():
        None

    else:
        fr = q.get()
        # Additional code

    time.sleep(1)

Динамические изменения 'q' происходят не очень часто, поэтому в большинстве случаев q.empty() будет истинным, но цикл должен быть готов, как только будут сделаны изменения. Мой вопрос в том, будет ли запуск этого кода в течение нескольких часов за один раз привести к тому, что память в конечном итоге закончится? Поскольку цикл while довольно короткий и работает практически без остановок, я подумал, что это может быть проблемой. Если это может быть причиной проблемы, есть ли у кого-нибудь предложения по улучшению кода, чтобы не вызывался убийца нехватки памяти?

Большое тебе спасибо.


person rmsrms1987    schedule 27.02.2014    source источник
comment
if q.empty(): pass — это идиоматический способ записи этого блока. Но было бы еще лучше просто иметь if not q.empty(): fr = q.get() в первую очередь.   -  person Henry Keiter    schedule 27.02.2014
comment
Какую реализацию вы используете? .get() удаляет элемент из очереди или только проверяет его? В последнем случае размер очереди монотонно увеличивается.   -  person Stefano Sanfilippo    schedule 27.02.2014
comment
у тебя своп включен? каков результат free?   -  person SingleNegationElimination    schedule 27.02.2014
comment
Спасибо за все комментарии. Я использую .get() для удаления списка из очереди. Итак, я использую .put() в основной программе, чтобы отправить список в параллельный процесс, а .get() - это то, что его подбирает. Ранее я предполагал, что после ввода .get() очередь очищается, но, возможно, я ошибаюсь.   -  person rmsrms1987    schedule 27.02.2014
comment
Некоторое время назад я прекратил запускать программу, но вот текущий вывод «свободно»: общее количество использованных свободных общих буферов кэшировано в памяти: 8177396 1659060 6518336 0 255036 560160 --/+ буферов/кеша: 843864 7333532 Подкачка: 10027004 869020 9157984   -  person rmsrms1987    schedule 27.02.2014
comment
Вы пытались изменить /proc/‹pid›/oom_score для своего процесса?   -  person Alexander Gryanko    schedule 28.02.2014


Ответы (2)


Единственный способ, которым вы можете исчерпать память так, как вы описываете, - это если вы используете все больше и больше памяти с течением времени. Цикл здесь не демонстрирует такое поведение, поэтому он не может (исключительно) нести ответственность за какие-либо ошибки памяти. Запуск жесткого бесконечного цикла может привести к ненужным процессорным циклам, но сам по себе он не может вызвать MemoryError, если только он не хранит данные в другом месте.

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

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

person Henry Keiter    schedule 27.02.2014
comment
Это не ответ. Разместите его как комментарий. - person Stefano Sanfilippo; 27.02.2014
comment
@Stefano Как это не ответ? "My question is, would running this code for multiple hours at a time cause the memory to eventually run low?" Ответ: Нет, данный код не может привести к нехватке памяти программой. - person Henry Keiter; 27.02.2014
comment
Ваш ответ гласит: Я не могу сделать вывод, что ваш код сам по себе вызывает эту ошибку, предоставьте дополнительную информацию. Это то, что я бы написал в комментарии. И этот кусок (псевдо) кода вполне может быть причиной, потому что вы не знаете, как ведет себя queue.get. - person Stefano Sanfilippo; 27.02.2014
comment
@Stefano Я предполагаю, из-за отсутствия другой информации, что он использует queue.Queue, что не приведет к такому поведению. Спрашивающий не просил нас найти утечку памяти, а скорее могла ли она быть вызвана узким циклом в параллельном процессе. Я отредактировал свой ответ, чтобы, надеюсь, читать меньше, как запрос на дополнительную информацию. - person Henry Keiter; 27.02.2014
comment
Вопрос не ограничивается строго циклом, может ли выполнение этого кода в течение нескольких часов привести к тому, что память в конечном итоге закончится?. И программисты должны остерегаться предположений. Если сомневаетесь, спросите у ОП. - person Stefano Sanfilippo; 27.02.2014

Вы можете преобразовать свою программу в службу Linux и установить ее политику oom для продолжения.

Вы можете проверить эту и эта ссылка для просмотра как посмотреть/отредактировать сервисные параметры и увидеть сервисный параметр политики oom соответственно.

person zenprogrammer    schedule 10.08.2020