17

例如,存储一百万(32 位)整数的列表需要多少内存?

alist = range(1000000) # or list(range(1000000)) in Python 3.0
4

5 回答 5

24

“这取决于。” Python 以这样一种方式为列表分配空间,以实现将元素附加到列表的摊销常数时间

在实践中,这对当前实现意味着......列表总是为元素的二次幂分配空间。所以 range(1000000) 实际上会分配一个足够大的列表来容纳 2^20 个元素(~ 104.5 万)。

这只是存储列表结构本身所需的空间(它是指向每个元素的 Python 对象的指针数组)。32 位系统每个元素需要 4 个字节,64 位系统每个元素需要 8 个字节。

此外,您需要空间来存储实际元素。这变化很大。对于小整数(目前是 -5 到 256),不需要额外的空间,但对于较大的数字,Python 会为每个整数分配一个新对象,这需要 10-100 个字节并且往往会导致内存碎片化。

底线:它很复杂,Python 列表不是存储大型同构数据结构的好方法。为此,请使用该array模块,或者,如果您需要进行矢量化数学,请使用 NumPy。

PS-元组与列表不同,它的设计目的不是让元素逐渐附加到它们上面。我不知道分配器是如何工作的,但甚至不考虑将它用于大型数据结构:-)

于 2008-09-25T20:10:53.893 回答
15

有用的链接:

如何获取python对象的内存大小/使用情况

python对象的内存大小?

如果将数据放入字典中,我们如何计算数据大小?

然而,他们并没有给出明确的答案。要走的路:

  1. 使用/不使用列表测量 Python 解释器消耗的内存(使用 OS 工具)。

  2. 使用定义某种 sizeof(PyObject) 的第三方扩展模块。

更新

配方 546530:Python 对象的大小(修订)

import asizeof

N = 1000000
print asizeof.asizeof(range(N)) / N
# -> 20 (python 2.5, WinXP, 32-bit Linux)
# -> 33 (64-bit Linux)
于 2008-09-25T21:00:40.327 回答
6

解决问题的“元组”部分

在典型的构建配置中声明 CPython 的 PyTuple 可以归结为:

struct PyTuple {
  size_t refcount; // tuple's reference count
  typeobject *type; // tuple type object
  size_t n_items; // number of items in tuple
  PyObject *items[1]; // contains space for n_items elements
};

PyTuple 实例的大小在构建过程中是固定的,之后无法更改。PyTuple 占用的字节数可以计算为

sizeof(size_t) x 2 + sizeof(void*) x (n_items + 1).

这给出了元组的大小。要获得完整大小,您还需要添加以PyTuple::items[]数组为根的对象图消耗的总字节数。

值得注意的是,元组构造例程确保只创建空元组的单个实例(单例)。

参考: Python.hobject.htupleobject.htupleobject.c

于 2008-09-26T13:08:27.510 回答
4

一个新函数getsizeof()接受一个 Python 对象并返回该对象使用的内存量,以字节为单位。内置对象返回正确的结果;第三方扩展可能没有,但可以定义一个 __sizeof__()方法来返回对象的大小。

kveretennicov@nosignal:~/py/r26rc2$ ./python
Python 2.6rc2 (r26rc2:66712, Sep  2 2008, 13:11:55) 
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
>>> import sys
>>> sys.getsizeof(range(1000000))
4000032
>>> sys.getsizeof(tuple(range(1000000)))
4000024

显然返回的数字不包括包含的对象消耗的内存(sys.getsizeof(1) == 12)。

于 2008-10-01T21:28:21.933 回答
2

这是特定于实现的,我很确定。当然,这取决于整数的内部表示——你不能假设它们会被存储为 32 位,因为 Python 为你提供了任意大的整数,所以小整数可能存储得更紧凑。

在我的 Python(核心 2 duo 上的 Fedora 9 上的 2.5.1)上,分配前的 VmSize 为 6896kB,之后为 22684kB。再分配一百万个元素后,VmSize 变为 38340kB。对于 1000000 个整数,这非常粗略地表明大约 16000kB,即每个整数大约 16 个字节。这表明列表的开销很大。我会用一大撮盐来接受这些数字。

于 2008-09-25T20:15:48.220 回答