ОС запускает процессы уничтожения при запуске многопоточного процесса python

Это самое странное!

У меня многопоточное клиентское приложение, написанное на Python. Я использую threading для одновременной загрузки и обработки страниц. Я бы использовал мультирум cURL, за исключением того, что узкое место, безусловно, является процессором (а не пропускной способностью) в этом приложении, поэтому более эффективно использовать пул потоков.

У меня есть 64-битная i7-качающая 16-гигабайтная оперативная память. Мускулистый. Я запускаю 80 потоков, слушая Pandora и троллинг Stackoverflow и BAM! Родительский процесс иногда заканчивается сообщением

Killed

В других случаях одна страница (которая является собственным процессом в Chrome) умрет. В других случаях происходит сбой всего браузера.

Если вы хотите увидеть немного кода, вот суть:

Вот родительский процесс:

def start( ):
 while True:
 for url in to_download:
 queue.put( ( url, uri_id ) )
 to_download = [ ]
 if queue.qsize( ) < BATCH_SIZE:
 to_download = get_more_urls( BATCH_SIZE )
 if threading.activeCount( ) < NUM_THREADS:
 for thread in threads:
 if not thread.isAlive( ):
 print "Respawning..."
 thread.join( )
 threads.remove( thread )
 t = ClientThread( queue )
 t.start( )
 threads.append( t )
 time.sleep( 0.5 )

И вот суть ClientThread:

class ClientThread( threading.Thread ):
 def __init__( self, queue ):
 threading.Thread.__init__( self )
 self.queue = queue
 def run( self ):
 while True:
 try:
 self.url, self.url_id = self.queue.get( )
 except:
 raise SystemExit
 html = StringIO.StringIO( )
 curl = pycurl.Curl( )
 curl.setopt( pycurl.URL, self.url )
 curl.setopt( pycurl.NOSIGNAL, True )
 curl.setopt( pycurl.WRITEFUNCTION, html.write )
 curl.close( )
 try:
 curl.perform( )
 except pycurl.error, error:
 errno, errstr = error
 print errstr
 curl.close( )

EDIT: О, правильно... забыл задать вопрос... должно быть очевидно: почему мои процессы убиты? Это происходит на уровне ОС? Уровень ядра? Это связано с ограничением количества открытых TCP-соединений, которые у меня есть? Это ограничение на количество потоков, которые я могу запустить сразу? Выходной сигнал cat /proc/sys/kernel/threads-max равен 257841. Итак... я не думаю, что....

Я думаю, что у меня это получилось... ОК... У меня нет своп-пространства на моем диске. Есть ли способ создать некоторое пространство подкачки? Я запускаю Fedora 16. Там WAS swap... затем я включил всю свою оперативную память, и она исчезла волшебным образом. Tailing /var/log/messages Я нашел эту ошибку:

Mar 26 19:54:03 gazelle kernel: [700140.851877] [15961] 500 15961 12455 7292 1 0 0 postgres
Mar 26 19:54:03 gazelle kernel: [700140.851880] Out of memory: Kill process 15258 (chrome) score 5 or sacrifice child
Mar 26 19:54:03 gazelle kernel: [700140.851883] Killed process 15258 (chrome) total-vm:214744kB, anon-rss:70660kB, file-rss:18956kB
Mar 26 19:54:05 gazelle dbus: [system] Activating service name='org.fedoraproject.***************' (using servicehelper)
2 ответа

Вы активировали обработчик ядра Out Of Memory (OOM); он выбирает, какие процессы убивать сложным способом, который пытается убить как можно меньше процессов, чтобы сделать наибольшее влияние. Chrome, по-видимому, делает наиболее привлекательным процесс для убийства по критериям, которые использует ядро.

Вы можете просмотреть сводку критериев в мастере proc(5) в файле /proc/[pid]/oom_score:

/proc/[pid]/oom_score (since Linux 2.6.11)
 This file displays the current score that the kernel
 gives to this process for the purpose of selecting a
 process for the OOM-killer. A higher score means that
 the process is more likely to be selected by the OOM-
 killer. The basis for this score is the amount of
 memory used by the process, with increases (+) or
 decreases (-) for factors including:
 * whether the process creates a lot of children using
 fork(2) (+);
 * whether the process has been running a long time, or
 has used a lot of CPU time (-);
 * whether the process has a low nice value (i.e., > 0)
 (+);
 * whether the process is privileged (-); and
 * whether the process is making direct hardware access
 (-).
 The oom_score also reflects the bit-shift adjustment
 specified by the oom_adj setting for the process.

Вы можете настроить файл oom_score для своей программы Python, если хотите, чтобы он был убит.

Вероятно, лучший подход заключается в добавлении большего количества свопов в вашу систему, чтобы попытаться оттолкнуть время, когда вызывается OOM-killer. Разумеется, наличие большего количества свопов не обязательно означает, что ваша система никогда не исчерпает память - и вам может не понравиться, как она обрабатывается, если есть большое количество swap-трафика, но она может по крайней мере получить вас в прошлом проблемы с памятью.

Если вы уже выделили все пространство для разделов подкачки, вы можете добавить файлы подкачки. Поскольку они проходят через файловую систему, для файлов подкачки есть больше накладных расходов, чем разделов подкачки, но вы можете добавить их после разделения диска, что делает его легким краткосрочным решением. Вы используете команду dd(1) для выделения файла (не использовать seek для создания разреженного файла), а затем используйте mkswap(8) для форматирования файла для использования подкачки, затем используйте swapon(8) для включения этого конкретного файла. (Я думаю, вы даже можете добавить файлы подкачки к fstab(5), чтобы они автоматически были доступны при следующей перезагрузке тоже, но я никогда не пробовал и не знаю синтаксиса.)


Вы делаете

raise SystemExit

который фактически завершает интерпретатор Python, а не поток, в котором вы работаете.

licensed under cc by-sa 3.0 with attribution.