Python 基本类型(特别是 int 和 float)的内存使用
Memory usage of Python base types (particulary int and float)
这是来自 Python 3.8.0 解释器的示例(但是,它在 3.7.5 中类似)
>>> import sys
>>> sys.getsizeof(int)
416
>>> sys.getsizeof(float)
416
>>> sys.getsizeof(list)
416
>>> sys.getsizeof(tuple)
416
>>> sys.getsizeof(dict)
416
>>> sys.getsizeof(bool)
416
getsizeof()
returns 对象消耗了多少字节 Python 以及垃圾收集器开销(参见 here)。 basic python 类 消耗相同内存量的原因是什么?
如果我们看一下这些实例 类
>>> import sys
>>> sys.getsizeof(int())
24
>>> sys.getsizeof(float())
24
默认参数是0
,这两个实例对该参数的内存使用量相同。但是,如果我尝试添加一个参数
>>> sys.getsizeof(int(1))
28
>>> sys.getsizeof(float(1))
24
这就是奇怪的地方。为什么int类型实例内存占用增加,float类型实例内存占用不增加?
查看 the docs,重要的是要观察到:
Only the memory consumption directly attributed to the object is accounted for, not the memory consumption of objects it refers to.
那么从sys.getsizeof(int(1))
的返回值大于sys.getsizeof(float(1))
的返回值,你能推断出什么?
简单地说,表示 int
比表示 float
需要更多的内存。这令人惊讶吗?好吧,可能不是,如果我们可以期望 "do more things" 与 int
相比,我们可以用 float
做到。我们可以通过查看属性的数量来衡量 "amount of functionality" 的第一个程度:
>>> len(dir(int))
70
>>> len(dir(float))
57
简而言之,这一切都归结为 Python 如何表示任意长整数。 float()
类型表示(有限)就像 C double
.
在 CPython 实现中,每个对象 (source) 都以引用计数和指向该对象类型对象的指针开始。那是 16 个字节。
Float 对象将其数据存储为 C double
(source),即 8 个字节。所以 16 + 8 = 24 字节 用于浮动对象。
使用整数,情况更复杂。整数对象表示为可变大小的对象 (source),它为 16 个字节添加了另外 8 个字节。
数字表示为数组。根据平台的不同,Python 使用具有 30 位数字的 32 位无符号整数数组或具有 15 位数字的 16 位无符号整数数组。所以对于小整数,数组中只有一个 32 位整数,所以再添加 4 个字节 = 16 + 8 + 4 = 28 个字节.
如果要表示更大的整数,大小会增加:
sys.getsizeof(int(2**32)) # prints 32 (24 + 2*4 bytes)
sys.getsizeof(int(2**64)) # prints 36 (24 + 3*4 bytes)
编辑:
使用 sys.getsizeof(int)
,您将获得 class 的大小,而不是 实例 的大小class。 float
、bool
、...
也是如此
print(type(int)) # prints <class 'type'>
如果您查看 source,就会发现引擎盖下有很多东西。在我的 Python 3.6.9 (Linux/64bit) 版本中,这会打印 400 个字节。
这是来自 Python 3.8.0 解释器的示例(但是,它在 3.7.5 中类似)
>>> import sys
>>> sys.getsizeof(int)
416
>>> sys.getsizeof(float)
416
>>> sys.getsizeof(list)
416
>>> sys.getsizeof(tuple)
416
>>> sys.getsizeof(dict)
416
>>> sys.getsizeof(bool)
416
getsizeof()
returns 对象消耗了多少字节 Python 以及垃圾收集器开销(参见 here)。 basic python 类 消耗相同内存量的原因是什么?
如果我们看一下这些实例 类
>>> import sys
>>> sys.getsizeof(int())
24
>>> sys.getsizeof(float())
24
默认参数是0
,这两个实例对该参数的内存使用量相同。但是,如果我尝试添加一个参数
>>> sys.getsizeof(int(1))
28
>>> sys.getsizeof(float(1))
24
这就是奇怪的地方。为什么int类型实例内存占用增加,float类型实例内存占用不增加?
查看 the docs,重要的是要观察到:
Only the memory consumption directly attributed to the object is accounted for, not the memory consumption of objects it refers to.
那么从sys.getsizeof(int(1))
的返回值大于sys.getsizeof(float(1))
的返回值,你能推断出什么?
简单地说,表示 int
比表示 float
需要更多的内存。这令人惊讶吗?好吧,可能不是,如果我们可以期望 "do more things" 与 int
相比,我们可以用 float
做到。我们可以通过查看属性的数量来衡量 "amount of functionality" 的第一个程度:
>>> len(dir(int))
70
>>> len(dir(float))
57
简而言之,这一切都归结为 Python 如何表示任意长整数。 float()
类型表示(有限)就像 C double
.
在 CPython 实现中,每个对象 (source) 都以引用计数和指向该对象类型对象的指针开始。那是 16 个字节。
Float 对象将其数据存储为 C double
(source),即 8 个字节。所以 16 + 8 = 24 字节 用于浮动对象。
使用整数,情况更复杂。整数对象表示为可变大小的对象 (source),它为 16 个字节添加了另外 8 个字节。 数字表示为数组。根据平台的不同,Python 使用具有 30 位数字的 32 位无符号整数数组或具有 15 位数字的 16 位无符号整数数组。所以对于小整数,数组中只有一个 32 位整数,所以再添加 4 个字节 = 16 + 8 + 4 = 28 个字节.
如果要表示更大的整数,大小会增加:
sys.getsizeof(int(2**32)) # prints 32 (24 + 2*4 bytes)
sys.getsizeof(int(2**64)) # prints 36 (24 + 3*4 bytes)
编辑:
使用 sys.getsizeof(int)
,您将获得 class 的大小,而不是 实例 的大小class。 float
、bool
、...
print(type(int)) # prints <class 'type'>
如果您查看 source,就会发现引擎盖下有很多东西。在我的 Python 3.6.9 (Linux/64bit) 版本中,这会打印 400 个字节。