python builtins中的垃圾收集 - 总和

时间:2012-08-30 18:01:28

标签: python garbage-collection

当我尝试在python解释器中运行以下代码时,它给了我一个明显的MemoryError,因为我正在运行一个无限循环以检查内存使用情况。

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

print sum(a())

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

3 个答案:

答案 0 :(得分:3)

如果python内置版有内存泄漏,那就是一个bug。

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

要检查实际的内存泄漏,一种方法是重复运行代码。如果它是真正的内存泄漏,那么每次运行它都会丢失内存。如果它是一个幻像内存泄漏,内存实际上会第二次被重用,你不会丢失任何内存。

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

答案 1 :(得分:2)

Free Lists上的GC上的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.

答案 2 :(得分:1)

这与sum,生成器或垃圾收集器的实现无关。

您所看到的不断增长的内存使用量是保持i值所需的内容。 Python支持任意大整数,每次迭代存储i所需的位数加倍。如果您将更改生成器功能更改为:

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

你会发现内存占用很稳定。