Python 结构的内存大小

是否有关于32位和64位平台上 Python 数据结构的内存大小的参考资料?

如果没有,这将是很好的,有它在所以。越详尽越好!那么下列 Python 结构使用了多少字节(取决于 len和相关的内容类型) ?

  • int
  • float
  • 参考文献
  • str
  • Unicode 字符串
  • tuple
  • list
  • dict
  • set
  • array.array
  • numpy.array
  • deque
  • 新样式类对象
  • 旧式类对象
  • 还有我忘记的一切!

(对于只保留对其他对象的引用的容器,我们显然不想计算项本身的大小,因为它可能是共享的。)

此外,是否有办法在运行时获得对象使用的内存(递归或非递归) ?

120696 次浏览

之前的问题就此提出的建议是使用 Getsizeof (),引述如下:

>>> import sys
>>> x = 2
>>> sys.getsizeof(x)
14
>>> sys.getsizeof(sys.getsizeof)
32
>>> sys.getsizeof('this')
38
>>> sys.getsizeof('this also')
48

你可以这样做:

>>> import sys
>>> import decimal
>>>
>>> d = {
...     "int": 0,
...     "float": 0.0,
...     "dict": dict(),
...     "set": set(),
...     "tuple": tuple(),
...     "list": list(),
...     "str": "a",
...     "unicode": u"a",
...     "decimal": decimal.Decimal(0),
...     "object": object(),
... }
>>> for k, v in sorted(d.iteritems()):
...     print k, sys.getsizeof(v)
...
decimal 40
dict 140
float 16
int 12
list 36
object 8
set 116
str 25
tuple 28
unicode 28

2012-09-30

Python 2.7(linux,32位) :

decimal 36
dict 136
float 16
int 12
list 32
object 8
set 112
str 22
tuple 24
unicode 32

Python 3.3(linux,32位)

decimal 52
dict 144
float 16
int 14
list 32
object 8
set 112
str 26
tuple 24
unicode 26

2016-08-01

OSX,Python 2.7.10(默认,Oct 232015,19:19:21)[ GCC 4.2.1 Compatible Apple LLVM 7.0.0(clang-700.0.59.5)] on darwin

decimal 80
dict 280
float 24
int 24
list 72
object 16
set 232
str 38
tuple 56
unicode 52

我一直很高兴地使用 Pympler来完成这样的任务。它与许多版本的 Python 兼容——特别是 asizeof模块可以追溯到2.2!

例如,使用 Hughdbrown 的示例,但是在开头和结尾使用 from pympler import asizeof,我看到(MacOSX 10.5上的系统 Python 2.5) :

$ python pymp.py
set 120
unicode 32
tuple 32
int 16
decimal 152
float 16
list 40
object 0
dict 144
str 32

显然这里有一些近似值,但是我发现它对于内存占用分析和调优非常有用。

试试内存分析器。 内存剖析器内存剖析器

Line #    Mem usage  Increment   Line Contents
==============================================
3                           @profile
4      5.97 MB    0.00 MB   def my_func():
5     13.61 MB    7.64 MB       a = [1] * (10 ** 6)
6    166.20 MB  152.59 MB       b = [2] * (2 * 10 ** 7)
7     13.61 MB -152.59 MB       del b
8     13.61 MB    0.00 MB       return a

也可以使用 孔雀鱼模块。

>>> from guppy import hpy; hp=hpy()
>>> hp.heap()
Partition of a set of 25853 objects. Total size = 3320992 bytes.
Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
0  11731  45   929072  28    929072  28 str
1   5832  23   469760  14   1398832  42 tuple
2    324   1   277728   8   1676560  50 dict (no owner)
3     70   0   216976   7   1893536  57 dict of module
4    199   1   210856   6   2104392  63 dict of type
5   1627   6   208256   6   2312648  70 types.CodeType
6   1592   6   191040   6   2503688  75 function
7    199   1   177008   5   2680696  81 type
8    124   0   135328   4   2816024  85 dict of class
9   1045   4    83600   3   2899624  87 __builtin__.wrapper_descriptor
<90 more rows. Type e.g. '_.more' to view.>

还有:

>>> hp.iso(1, [1], "1", (1,), {1:1}, None)
Partition of a set of 6 objects. Total size = 560 bytes.
Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
0      1  17      280  50       280  50 dict (no owner)
1      1  17      136  24       416  74 list
2      1  17       64  11       480  86 tuple
3      1  17       40   7       520  93 str
4      1  17       24   4       544  97 int
5      1  17       16   3       560 100 types.NoneType

这些答案都收集了浅层大小的信息。我怀疑这个问题的访问者最终会在这里寻找答案: “这个复杂的物体在内存中有多大?”

这里有一个很好的答案: https://goshippo.com/blog/measure-real-size-any-python-object/

笑点:

import sys


def get_size(obj, seen=None):
"""Recursively finds size of objects"""
size = sys.getsizeof(obj)
if seen is None:
seen = set()
obj_id = id(obj)
if obj_id in seen:
return 0
# Important mark as seen *before* entering recursion to gracefully handle
# self-referential objects
seen.add(obj_id)
if isinstance(obj, dict):
size += sum([get_size(v, seen) for v in obj.values()])
size += sum([get_size(k, seen) for k in obj.keys()])
elif hasattr(obj, '__dict__'):
size += get_size(obj.__dict__, seen)
elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes, bytearray)):
size += sum([get_size(i, seen) for i in obj])
return size

用法如下:

In [1]: get_size(1)
Out[1]: 24


In [2]: get_size([1])
Out[2]: 104


In [3]: get_size([[1]])
Out[3]: 184

如果您想更深入地了解 Python 的内存模型,这里有一篇很棒的文章,其中有类似的“总大小”代码片段,作为更长解释的一部分: https://code.tutsplus.com/tutorials/understand-how-much-memory-your-python-objects-use--cms-25609

使用 dir([object])内置函数时,可以获得内置函数的 __sizeof__

>>> a = -1
>>> a.__sizeof__()
24

还可以利用 Python 标准库中的 tracemalloc模块。对于类是用 C 语言实现的对象(例如,与 Pympler 不同) ,它似乎工作得很好。