读取 Python 的输出 memory_profiler

Reading the output of Pythons memory_profiler

我无法理解 memory_profilers 的输出。基本上,它看起来像这样:

Filename: tspviz.py

Line #    Mem usage    Increment   Line Contents
================================================
     7  34.589844 MiB  34.589844 MiB   @profile(precision=6)
     8                             def parse_arguments():
     9  34.917969 MiB   0.328125 MiB       a = [x**2 for x in range(10000)]

在第 9 行我们可以清楚地看到,我们使用了一些内存。现在,我用 sys.getsizeof() 测量了这个列表的大小。我仔细检查了它是否实际上是一个整数列表:

print(sys.getsizeof(a))
print(type(a[0]))

这就是我得到的:

87624
<class 'int'>

嗯,现在有问题了。正如我检查的那样,f.e Python 中的 int 在我的 64 位 Windows 机器上的大小为 28。我不知道这是否正确。但是就算是这样。 10000 * 28 = 0.28 MB。和 0.28 MB = 0.267028809 MiBmemory_profiler 的输出显示 MiB)。现在的问题是,在 table 中有 0.328125 MiB,所以差异是 0.061096191 MB。

我担心的是,在 Python 中构建列表真的需要大量内存,还是我以错误的方式解释了某些内容?

和P.S:为什么,当这个a列表的长度为1000000时,当我创建它时,该行的Increment列中的数字,就像 -9xxx MiB?我的意思是为什么是负数?

Python 列表不存储对象本身,而是存储对对象的引用。 Python 的 64 位版本每个引用使用 8 个字节,因此 10000 int 需要 80000 个字节。从您的示例中,sys.getsizeof(a) 返回了 87624,因为为了提高效率,列表会根据其大小分配额外的 space。 See this post for more.

int 占用的 space 取决于它的大小,但是 int2^30-1 确实在 64- 上占用 28 个字节位 Python(0 除外,它仅占用 24 个字节)。所以总的来说,列表占用的大小是 87624 + 279996 = 367620 字节,大约是 0.35 MiB.

这与 memory_profiler 的输出之间的差异可能是由于 this:

This module gets the memory consumption by querying the operating system kernel about the amount of memory the current process has allocated, which might be slightly different from the amount of memory that is actually used by the Python interpreter. Also, because of how the garbage collector works in Python the result might be different between platforms and even between runs.