考虑非常简单的代码:
#!/usr/bin/python
from multiprocessing import Pool
import random
def f(x):
return x*x
def sampleiter(n):
num = 0
while num < n:
rand = random.random()
yield rand
num += 1
if __name__ == '__main__':
pool = Pool(processes=4) # start 4 worker processes
for item in pool.imap_unordered(f, sampleiter(100000000000000), 20):
print item
pool.close
在终端中运行时,Python泄漏内存 可能有什么不对?
答案 0 :(得分:4)
输出缓冲不是问题(或者至少不是唯一的问题),因为(a)Python进程本身在内存中增长,(b)如果你重定向到/dev/null
,它仍然会发生。
我认为问题在于,当您打印出结果时,池返回结果的速度远远超过它们可以消耗的速度,因此很多很多结果都存储在内存中。如果您查看the source of the class that does this,则中间结果会存储在名为collections.deque
的{{1}}中;我打赌_items
变得越来越大。
我不完全确定如何测试它,因为即使imap_unordered
returns an instance of this class你似乎仍然只能使用生成器方法:
_items
更新:如果您向In [8]: r = pool.imap_unordered(f, sampleiter(1e8), 20)
In [9]: print dir(r)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__',
'__init__', '__iter__', '__name__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'close', 'gi_code', 'gi_frame', 'gi_running', 'next', 'send', 'throw']
添加time.sleep(.01)
,内存使用率将保持不变。所以,是的,问题在于你比你使用它们更快地产生结果。
(顺便说一下:你的意思是代码示例末尾的f()
; pool.close()
只是对函数的引用,实际上并没有调用它。)
答案 1 :(得分:2)
我在这里看到的导致内存泄漏的唯一变量是print语句。当我用print item
替换pass
时,内存保持低位且不变。当你打印时,我不确定引擎盖下到底发生了什么,但它显然堆积了一些东西而不是自由。此外,当我将块大小降低到1时,内存增加得更慢(显然),但也需要更长时间。所以它确实会增加内存使用量。
发现这是由于终端的历史缓冲区(而不是python进程本身)而导致内存使用量增加的具体参考:Memory leak when running python in Mac OS Terminal