2016-02-11 32 views
1

我試圖創建一個大小爲1 MB的列表。而下面的代碼工作:sys.getsizeof()結果與結構大小不完全相關

dummy = ['a' for i in xrange(0, 1024)] 
sys.getsizeof(dummy) 
Out[1]: 9032 

以下代碼不起作用。

import os 
import sys 

dummy = [] 
dummy.append((os.urandom(1024)) 
sys.getsizeof(dummy) 
Out[1]: 104 

有人可以解釋爲什麼嗎?

如果您想知道爲什麼我不使用第一個代碼片段,我正在編寫一個程序,通過編寫for循環將基準塊(大小爲1 B,1 KB和1 MB)寫入內存來測試我的內存。

start = time.time() 
for i in xrange(1, (1024 * 10)): 
    dummy.append(os.urandom(1024)) #loop to write 1 MB blocks into memory 
end = time.time() 
+0

也許它可以幫助:'sys.getsizeof(b「a」*(1024-37))' –

+1

你不會在你的代碼旁邊發生很多其他事情的時候獲得一個理智的基準。 Python是這個任務的一個可怕的工具選擇。 –

回答

2

如果您檢查列表的大小,它將提供列表數據結構的大小,包括指向其組成元素的指針。它不會考慮元素的大小。

str1_size = sys.getsizeof(['a' for i in xrange(0, 1024)]) 
str2_size = sys.getsizeof(['abc' for i in xrange(0, 1024)]) 
int_size = sys.getsizeof([123 for i in xrange(0, 1024)]) 
none_size = sys.getsizeof([None for i in xrange(0, 1024)]) 
str1_size == str2_size == int_size == none_size 

空列表的大小:sys.getsizeof([]) == 72
添加的元素:sys.getsizeof([1]) == 80
添加另一個元件:sys.getsizeof([1, 1]) == 88
因此,每個元件增加了4個字節。
要獲得1024字節,我們需要(1024 - 72)/8 = 119元素。

119個元素的列表大小:sys.getsizeof([None for i in xrange(0, 119)]) == 1080
這是因爲列表維護用於插入更多項目的額外緩衝區,以便它不必每次調整大小。 (尺寸與107和126之間的元素數量相同爲1080)。

所以我們需要的是一個不可變的數據結構,它不需要保留這個緩衝區 - tuple

empty_tuple_size = sys.getsizeof(())      # 56 
single_element_size = sys.getsizeof((1,))    # 64 
pointer_size = single_element_size - empty_tuple_size # 8 
n_1mb = (1024 - empty_tuple_size)/pointer_size   # (1024 - 56)/8 = 121 
tuple_1mb = (1,) * n_1mb 
sys.getsizeof(tuple_1mb) == 1024 

因此,這是你的答案得到一個1MB的數據結構:(1,)*121

但是請注意,這只是元組和組成指針的大小。對於總大小,實際上需要將各個元素的大小相加。


備選:

sys.getsizeof('') == 37 
sys.getsizeof('1') == 38  # each character adds 1 byte 

爲1 MB,我們需要987個字符:

sys.getsizeof('1'*987) == 1024 

而且這是實際的大小,而不是指針的只是大小。