这是最奇怪的事情!
我有一个用Python编写的多线程客户端应用程序。我正在使用线程来同时下载和处理页面。我会使用cURL多句柄,除了瓶颈肯定是此应用程序中的处理器(而不是带宽),因此使用线程池更有效。
我有64b i7摇摆16GB内存。仡。我在听Pandora和拖钓Stackoverflow和BAM时启动80个线程!父进程有时以消息
结束 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( )
编辑:哦,对了...忘了问这个问题......应该是显而易见的:为什么我的进程会被杀死?它是否发生在操作系统级别?内核级别?这是由于我可以拥有的开放TCP连接数量的限制吗?这是我一次可以运行的线程数限制吗? cat /proc/sys/kernel/threads-max
的输出为257841
。所以......我不认为那是......
我想我已经拥有了......好吧......我的驱动器上根本没有交换空间。有没有办法现在创建一些交换空间?我正在运行Fedora 16.有WAS交换...然后我启用了所有的RAM,它神奇地消失了。拖尾/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.Setroubleshootd' (using servicehelper)
答案 0 :(得分:7)
你已经触发了内核的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.
如果您希望Python程序被杀死,可以调整Python程序的oom_score
文件。
可能更好的方法是在系统中添加更多交换,以试图推迟调用OOM杀手的时间。当然,拥有更多交换并不一定意味着您的系统永远不会耗尽内存 - 如果有大量的交换流量,您可能不关心它处理的方式 - 但它至少可以让您过去紧张记忆问题。
如果您已经为交换分区分配了所有可用空间,则可以添加swap 文件。因为它们通过文件系统,交换文件的开销比交换分区多,但是您可以在驱动器分区后添加它们,这使它成为一个简单的短期解决方案。您使用dd(1)
命令分配文件(不使用seek
制作稀疏文件),然后使用mkswap(8)
格式化文件以进行交换使用,然后使用swapon(8)
打开该特定文件。 (我认为你甚至可以将交换文件添加到fstab(5)
以使它们在下次重启时自动可用,但我从未尝试过,也不知道语法。)
答案 1 :(得分:0)
你正在做一个
raise SystemExit
实际上退出了Python解释器而不是你正在运行的线程。