Python 占用过多内存的对象列表

Python list of Objects taking up too much memory

我有以下代码,它创建了 class foo 的一百万个对象:

for i in range(1000000):
    bar = foo()
    list_bar.append(bar)

bar 对象只有 96 字节,由 getsizeof() 确定。但是,追加步骤需要将近 8GB 的​​内存。一旦代码退出循环,ram 使用量就会下降到预期的数量(列表的大小 + 一些开销~103MB)。只有当循环是 运行 时,ram 使用率才会飙升。为什么会这样?任何解决方法? PS: 使用生成器不是一个选项,它必须是一个列表。

编辑: xrange 没有帮助,使用 Python 3. 内存使用率仅在循环执行期间保持高位,并在循环执行后下降循环通过。 append 会不会有一些不明显的开销?

这很可能是由于 foo() 构造函数进行了一些无意的 周期性 引用;通常 Python 对象会在引用计数降为零时立即释放内存;现在,当垃圾收集器有机会 运行.

时,这些将在稍后被释放

您可以尝试在 10000 次迭代后强制 GC 运行 以查看它是否保持内存使用不变。

import gc
n = 1000000
list_bar = [ None ] * n
for i in range(n):
    list_bar[i] = foo()
    if i % 10000 == 0:
        gc.collect()

如果这减轻了内存压力,那么内存使用是因为一些引用循环。


调整列表大小会产生一些开销。如果你知道有多少个元素,那么你可以预先创建列表,例如:

list_bar = [ foo() for _ in xrange(1000000) ]

应该知道数组的大小而不需要调整它的大小;或创建包含 None:

的列表
n = 1000000
list_bar = [ None ] * n
for i in range(n):
    list_bar[i] = foo()

append 应该使用 realloc 来增加列表,但是旧的内存应该尽快释放;总而言之,对于最后为 100 MB 的列表,分配的所有内存的开销不应总计为 8G;操作系统可能错误地计算了使用的内存。

您如何衡量内存使用情况?

我怀疑您对第 3 方模块的使用可能是原因。也许第 3 方模块在初始化时暂时使用了大量内存。

此外,sys.getsizeof() 并不是对象所使用内存的准确指示。

例如:

from sys import getsizeof

class A(object):
    pass

class B(object):
    def __init__(self):
        self.big = 'a' * 1024*1024*1024    # approx. 1 GiB

>>> getsizeof(A)
976
>>> a = A()
>>> getsizeof(a)
64
>>> 
>>> getsizeof(B)
976
>>> b = B()
>>> getsizeof(b)
64
>>> getsizeof(b.big)
1073741873

实例化 b = B() 后,top 报告大约 1GiB 常驻内存使用情况。显然,getsizeof(b) 没有反映出来,returns 只有 64 个字节。