[英]Why does my class cost so much memory?
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
。 真是難以置信,為什么呢?
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
對象則對雙精度浮點數進行建模。 因此,該實例僅將2 * 24字節(在我的Mac上)用於這些浮點數,而數組中每個單精度'f'
值僅使用4字節。 Demo
實例,還需要創建一個list
對象,該list
對象的大小可以處理至少 500萬個對象引用。 該array
直接存儲C單精度浮點數。 hp.heap()
輸出僅計算實例占用空間,不計算每行中引用的float
值,但總計相符:
Demo
實例的320.000.000字節的內存。 float
實例的240.000.000字節的內存,再加上別處引用的108個float
。 這兩個組一起構成了堆中1500萬個Python對象的大部分。
list
對象包含500萬個指針,即指向所有Demo
實例的40.000.000字節,再加上該對象的記帳開銷。 堆上還有367個列表,被其他Python代碼引用。 array
實例(每500萬個4字節浮點數)為40.000.000字節,加上每個數組開銷56字節。 因此, array
對象存儲大量數字值的效率要高得多 ,因為它會將這些值存儲為原始C值。 但是,缺點是Python必須將您嘗試訪問的每個值裝箱 。 因此訪問ar[10]
返回一個Python float
對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.