python - cpython 2.7 中的内存泄漏

标签 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 表示存在很大的[匿名]内存。

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/

相关文章:

python - 考虑到 GIL,asyncio 怎么可能不是线程安全的?

python - 为什么这个正则表达式不匹配?

Python NameError 麻烦

python - Python-使用GET流式传输Youtube视频

memory - 汇编 - 尝试反转字符串,但它在最终字符串上添加了一个额外的字符

c++ - .NET 查看其他应用程序的内存

CUDA:使用网格跨步循环减少共享内存

python - Cython 从现有数组和变量创建新数组的最快方法是什么

python - 创建图像的函数 imshow 出错

python - Tkinter KeyPress 和 KeyRelease 事件