ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Python中包含一百万个元素的列表会占用多少内存?

2019-09-29 15:55:20  阅读:649  来源: 互联网

标签:python arrays memory reddit


根据redditmetrics.com,Reddit上有超过一百万个子评价.

我写了一个脚本,反复查询this Reddit API endpoint,直到所有的subreddits都存储在一个数组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
]

这个列表占用的内存空间大约是多少?

解决方法:

这取决于你的Python版本和你的系统,但我会帮你弄清楚它需要多少内存.首先,sys.getsizeof只返回表示容器的对象的内存使用,而不是容器中的所有元素.

Only the memory consumption directly attributed to the object is
accounted for, not the memory consumption of objects it refers to.

If given, default will be returned if the object does not provide
means to retrieve the size. Otherwise a TypeError will be raised.

getsizeof() calls the object’s __sizeof__ method and adds an
additional garbage collector overhead if the object is managed by the
garbage collector.

See 07001 for an example of using getsizeof()
recursively to find the size of containers and all their contents.

所以,我已经在交互式解释器会话中加载了该配方:

因此,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千兆字节的内存.使用recipie和更现实的字典:

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演出.现在,这在现代系统上并不是很多.但是如果你想节省空间,你应该使用一个元组甚至更好,一个命名元组:

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就像一个元组一样工作,但你可以访问带有名字的字段:

In [30]: r = x[0]

In [31]: r.name
Out[31]: 'my name is what'

In [32]: r.subscribers
Out[32]: 23456644

标签:python,arrays,memory,reddit
来源: https://codeday.me/bug/20190929/1832148.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有