簡體   English   中英

為什么我的課要花這么多內存?

[英]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()實例和數組之間有一些區別:

  • 實例具有最小的開銷來支持引用計數和弱引用,並包含指向其類的指針。 數組直接存儲值,而沒有任何開銷。
  • 該實例存儲Python浮點數。 這些都是成熟的對象,包括引用計數和弱引用支持。 該數組將單精度浮點數存儲為C值,而Python float對象則對精度浮點數進行建模。 因此,該實例僅將2 * 24字節(在我的Mac上)用於這些浮點數,而數組中每個單精度'f'值僅使用4字節。
  • 要跟蹤500萬個Demo實例,還需要創建一個list對象,該list對象的大小可以處理至少 500萬個對象引用。 array直接存儲C單精度浮點數。

hp.heap()輸出僅計算實例占用空間,不計算每行中引用的float值,但總計相符:

  • 500萬乘以64字節是Demo實例的320.000.000字節的內存。
  • 1000萬乘以24字節是float實例的240.000.000字節的內存,再加上別處引用的108個float

這兩個組一起構成了堆中1500萬個Python對象的大部分。

  • 您創建的用於保存實例的list對象包含500萬個指針,即指向所有Demo實例的40.000.000字節,再加上該對象的記帳開銷。 堆上還有367個列表,被其他Python代碼引用。
  • 2個array實例(每500萬個4字節浮點數)為40.000.000字節,加上每個數組開銷56字節。

因此, array對象存儲大量數字值的效率高得多 ,因為它會將這些值存儲為原始C值。 但是,缺點是Python必須將您嘗試訪問的每個值裝箱 因此訪問ar[10]返回一個Python float對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM