from guppy import hpy
hp = hpy()
class Demo(object):
__slots__ = ('v0', 'v1')
def __init__(self, v0, v1):
self.v0 = v0
self.v1 = v1
from array import array
value = 1.01
ar = array('f')
ar2 = array('f')
for i in range(5000000):
ar.append(value + i)
ar2.append(value + i * 0.1 + i * 0.01 + i * 0.001 + i * 0.0001 + i * 0.000001)
a = []
for i in range(5000000):
vex = Demo(ar[i], ar[2])
a.append(vex)
print "Heap at the end of the functionn", hp.heap()
这是输出:
Heap at the end of the functionn Partition of a set of 15063247 objects. Total size = 650251664 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 5000000 33 320000000 49 320000000 49 __main__.Demo
1 10000108 66 240002592 37 560002592 86 float
2 368 0 42008896 6 602011488 93 list
3 2 0 40000112 6 642011600 99 array.array
4 28182 0 2214784 0 644226384 99 str
5 12741 0 1058448 0 645284832 99 tuple
6 189 0 669624 0 645954456 99 dict of module
7 371 0 588104 0 646542560 99 dict (no owner)
8 258 0 509232 0 647051792 100 dict of sip.wrappertype
9 3176 0 406528 0 647458320 100 types.CodeType
我想知道Demo课为什么要花这么多内存。因为Demo类只保留float的引用,所以它不会复制float值。
getSizeOf(Demo) # 984
50W的演示类可能只需花费内存:984*50W=40215176
但现在花费320000000
。
令人难以置信,为什么?
答案 0 :(得分:3)
sys.getsizeof()
不会递归到子对象中,您只获取了类的大小,而不是实例的大小。每个实例占用64个字节,加上每个float
对象24个字节(在OS X上,使用Python 2.7.12):
>>> d = Demo(1.0, 2.0)
>>> sys.getsizeof(d)
64
>>> sys.getsizeof(d.v0)
24
>>> sys.getsizeof(d) + sys.getsizeof(d.v0) + sys.getsizeof(d.v1)
112
每个插槽仅为实例对象中的指针保留内存;在我的机器上,每个指针8个字节。
Demo()
个实例和数组之间存在几个差异:
float
对象模型 double 精度浮点数。因此,实例使用2 * 24字节(在我的Mac上)仅用于那些浮点数,而在数组中每个单精度'f'
值仅使用4个字节。Demo
个实例,您还需要创建一个list
对象,其大小可以处理至少 500万个对象引用。 array
直接存储C单精度浮点数。 hp.heap()
输出仅计算实例占用空间,而不计算每行的引用float
值,但总计匹配:
Demo
个实例的320.000.000字节内存。float
个实例的240.000.000字节内存,再加上其他地方引用的108个浮点数。这两个组一起组成了堆上1500万个Python对象的大部分。
list
对象包含500万个指针,即指向所有Demo
实例的40.000.000字节,以及该对象的会计开销。堆上还有367个列表,由其他Python代码引用。array
个实例是40.000.000字节,每个数组开销加56个字节。所以array
对象非常高效来存储大量数值,因为它将这些值存储为原始C值。但是,缺点是Python必须 box 您尝试访问的每个值;所以访问ar[10]
会返回一个Python float
对象。