例如,我有一个生成许多整数的代码。
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 表示存在很大的[匿名]内存。
Python 3.4 没有这样的行为:当我删除此处的列表时,内存会被释放!
会发生什么? python 是否将整数保留在内存中?
最佳答案
这是我复制它的方法。如果我启动 python 2.7,解释器将使用大约 4.5 MB 的内存。 (我引用了 Mac OS X Activity Monitor.app 中的“Real Mem”值)。
>>> 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 maintains an internal free list for integer objects. Unfortunately, that free list is both immortal and unbounded in size. floats also use an immortal & unbounded free list.
本质上,Python 将整数视为单例,假设您可能多次使用它们。
考虑一下:
# 4.5 MB
>>> a = [object() for i in xrange(10000000)]
# 166.7 MB
>>> del a
# 9.1 MB
在这种情况下,Python 很明显 Python 没有将对象
保留在内存中,并且删除a
会触发垃圾收集,从而清理所有内容。
我记得,Python 实际上会永远在内存中保留低值整数(0 - 1000 左右)。这可以解释为什么 gc.collect()
调用不会返回与删除对象列表
一样多的内存。
我环顾四周PEPs稍微弄清楚为什么 Python3 不同。然而,我没有看到任何明显的东西。如果您真的想知道,您可以深入研究源代码。
可以说,在 Python 3 中,要么数字单例行为发生了变化,要么垃圾收集器变得更好。
Python 3 中的许多功能都变得更好。
关于python - cpython 2.7 中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31951611/