2012-08-30 31 views
2

当我尝试在python解释器中运行下面的代码时,它会给我一个明显的MemoryError,因为我正在运行无限循环以检查内存使用情况。python buildins中的垃圾回收 - 总和

def a(): 
i=2 
while True: 
    yield i 
    i*=i 

print sum(a()) 

当我运行这段代码时,我可以看到python的内存使用增长。但是,当我得到一个MemoryError时,我可以看到python解释器进程仍然保持大约200 MB的内存,即使sum函数不再运行在解释器中。 我的问题是:即使在垃圾收集方面,python的内置函数是否应该不是非常有效?内置的垃圾收集器不会处理垃圾收集的责任,而是不清理自己的混乱?

+0

Python对Integer的内存管理比“内存泄漏和垃圾收集”要复杂一点,你可能想看看这里的解释:http://www.laurentluce.com/posts/python-integer-objects -implementation/ –

回答

2

Python文档在GC上:

并非所有在一些免费的列表中的项目可能会被释放,由于特定的实现,特别是int和float。

所以分配经由发电机一个极大无限整数会吃掉你所有的内存(最大接收内存错误),而不是所有的项目可能会被释放按照上面的定义。

但是,内存消失了吗?不可以。环境可以让代码重复使用。垃圾收集“高效”并不意味着它会收回物体离开作用域的时刻。它也可能意味着“让我们继续使用刚刚使用过的内存,也许这段愚蠢的代码会再次使用它。“

或者为Effbot告诉我们:这是返回给定的分配将由分配器被重用

内存,即使它没有返回到系统

可以force a GC collection,但这实际上可能会阻碍表现,除非你知道为什么并且有一个非常非常好的理由来强制它。

gc.collect([generation]) 
With no arguments, run a full collection. The optional argument generation may be an integer specifying which generation to collect (from 0 to 2). A ValueError is raised if the generation number is invalid. The number of unreachable objects found is returned. 

Changed in version 2.5: The optional generation argument was added. 

Changed in version 2.6: The free lists maintained for a number of built-in types are cleared whenever a full collection or collection of the highest generation (2) is run. Not all items in some free lists may be freed due to the particular implementation, in particular int and float. 
3

如果python内建函数有内存泄漏,那它就是一个bug。

但是,只是因为python仍然坚持内存并不意味着有内存泄漏。 Python有各种有趣的分配技巧,所以它可能会保留你的内存以备将来使用。所以你不能简单地在任务管理器中查看python是否正确处理内存。

要检查实际的内存泄漏,一种技巧是反复运行您的代码。如果它真的发生内存泄漏,每次运行时都会丢失内存。如果它的幻影内存泄漏,内存将被实际上第二次重用,并且不会丢失任何内存。

我在Linux机器上运行了你的代码,虽然我确实发现它在运行该循环一段时间后使用了更多的内存,而不是之前,再次运行它没有使用额外的内存,实际上一些内存在第一轮中失去的记忆似乎已经恢复。

1

这与sum,生成器或垃圾回收器的执行无关。

您所看到的日益增长的内存使用量是持有i的值所需的内存。 Python支持任意大的整数,并且每次迭代都需要存储i双精度的位数。如果你改变你的改变你的发电机功能为:

def a(): 
    i=2 
    while True: 
     yield i 
     i += 1 

你会看到内存占用是稳定的。

+0

我认为OP感兴趣的是为什么当总和终止时他没有回到内存,而不是为什么它会增加内存使用量。 –

+0

总和不会终止。 –