内存泄漏在cpython 2.7

时间:2015-08-11 20:44:35

标签: python memory cpython

例如,我有一个产生许多整数的代码。

import sys
import random
a = [random.randint(0, sys.maxint) for i in xrange(10000000)]

运行后我得到了VIRT 350M,RES 320M(以htop查看)。

然后我做:

del a

但是记忆仍然是VIRT 272M,RES 242M(产生整数之前是VIRT 24M,RES 6M)。

一个进程的pmap说有很多[anon]内存。

Python 3.4没有这样的行为:当我在这里删除列表时,内存可以释放!

会发生什么? python会将整数留在内存中吗?

1 个答案:

答案 0 :(得分:1)

这是我如何复制它。如果我启动python 2.7,解释器使用大约4.5 MB的内存。 (我引用" Real Mem"来自Mac OS X Activity Monitor.app的值。)

>>> a = [random.randint(0, sys.maxint) for i in xrange(10000000)]

现在,内存使用量约为305.7 MB。

>>> del a

删除a似乎对内存没有影响。

>>> import gc
>>> gc.collect()   # perform a full collection

现在,内存使用量为27.7 MB。有时,第一次拨打collect()似乎没有做任何事情,但第二次collect()电话会清理。

但是,这种行为是设计的, Python并没有泄漏。 This old FAQ在effbot.org上解释了更多关于发生了什么的事情:

  

“For speed”,Python维护整数对象的内部空闲列表。不幸的是,这个免费清单既是不朽的,也是无限的。花车也使用不朽的&无限的免费清单。

基本上,python将整数视为单例,假设您可能不止一次使用它们。

考虑一下:

# 4.5 MB    
>>> a = [object() for i in xrange(10000000)]
# 166.7 MB
>>> del a
# 9.1 MB

在这种情况下,python很明显python没有将object保留在内存中,并且删除a会触发垃圾收集,从而清除所有内容。

我记得,python实际上会永远保留内存中的低值整数(0 - 1000左右)。这可以解释为什么gc.collect()调用没有返回与删除objects列表一样多的内存。

我仔细研究了PEPs以找出Python3与众不同的原因。但是,我没有看到任何明显的东西。如果真的想知道,你可以在源代码中挖掘。

在Python 3中可以说,数字单例行为已经改变,或者垃圾收集器变得更好。

Python 3中有很多东西比较好。