我编写了一个脚本,反复查询redditmetrics.com,直到所有子编辑都存储在数组中all_subs
:
all_subs = []
for sub in <repeated request here>:
all_subs.append({"name": display_name, "subscribers": subscriber_count})
该脚本已经运行了近十个小时,大约已经完成了一半(每三个或四个请求就会受到速率限制)。当它完成后,我期待一个像这样的数组:
[
{ "name": "AskReddit", "subscribers", 16751677 },
{ "name": "news", "subscribers", 13860169 },
{ "name": "politics", "subscribers", 3350326 },
... # plus one million more entries
]
此列表占用的内存空间大约占多少?
答案 0 :(得分:13)
这取决于你的Python版本和你的系统,但我会帮你弄清楚需要多少内存。首先,sys.getsizeof
仅返回表示容器的对象的内存使用,而不是容器中的所有元素。
只有直接归因于对象的内存消耗才是 占了,而不是它所指对象的内存消耗。
如果给定,则在对象未提供时将返回default 意味着检索大小。否则会引发TypeError。
getsizeof()
调用对象的__sizeof__
方法并添加一个 如果对象由管理,则额外的垃圾收集器开销 垃圾收集器。有关使用
getsizeof()
的示例,请参阅recursive sizeof recipe 递归地查找容器及其所有内容的大小。
所以,我在交互式翻译会话中加载了这个食谱:
因此,CPython 列表实际上是一个异质的,可调整大小的arraylist。底层数组只包含指向Py_Objects的指针。因此,指针占用了一个值得记忆的机器字。在64位系统上,这是64位,因此是8个字节。因此,仅用于容器大小为1,000,000的列表将占用大约800万字节或8兆字节。建立一个包含1000000个条目的列表可以解决这个问题:
In [6]: for i in range(1000000):
...: x.append([])
...:
In [7]: import sys
In [8]: sys.getsizeof(x)
Out[8]: 8697464
额外的内存由python对象的开销和底层数组在末尾留下的额外空间来计算,以便进行高效的.append
操作。
现在,字典在Python中相当重要。只是容器:
In [10]: sys.getsizeof({})
Out[10]: 288
因此,大小为100万个dicts的下限是:288000000个字节。所以,粗略的下限:
In [12]: 1000000*288 + 1000000*8
Out[12]: 296000000
In [13]: 296000000 * 1e-9 # gigabytes
Out[13]: 0.29600000000000004
所以你可以期待大约0.3千兆字节的内存。使用收件人和更真实的dict
:
In [16]: x = []
...: for i in range(1000000):
...: x.append(dict(name="my name is what", subscribers=23456644))
...:
In [17]: total_size(x)
Out[17]: 296697669
In [18]:
所以,约0.3演出。现在,在现代系统上并不是很多。但是如果你想节省空间,你应该使用tuple
甚至更好的namedtuple
:
In [24]: from collections import namedtuple
In [25]: Record = namedtuple('Record', "name subscribers")
In [26]: x = []
...: for i in range(1000000):
...: x.append(Record(name="my name is what", subscribers=23456644))
...:
In [27]: total_size(x)
Out[27]: 72697556
或者,以千兆字节为单位:
In [29]: total_size(x)*1e-9
Out[29]: 0.07269755600000001
namedtuple
就像tuple
一样,但您可以使用名称访问字段:
In [30]: r = x[0]
In [31]: r.name
Out[31]: 'my name is what'
In [32]: r.subscribers
Out[32]: 23456644