『Python』記憶體分析_list和array的記憶體增長模式

來源:互聯網
上載者:User

標籤:highlight   size   inf   方法   整數   注意   輸出   估算   port   

『Python』記憶體分析_List對象記憶體佔用分析

在Python中,列表是一個動態指標數組,而array模組所提供的array對象則是儲存相同類型的數值的動態數組。由於array直接儲存值,因此它所使用的記憶體比列表少。列表和array都是動態數組,因此往其中添加新元素,而沒有空間儲存新的元素時,它們會自動重新分配記憶體塊,並將原來的記憶體中的值複製到新的記憶體塊中。為了減少重新分配記憶體的次數,通常每次重新分配時,大小都為原來的k倍。k值越大,則重新分配記憶體的次數越少,但浪費的空間越多。本節通過一系列的實驗觀察列表和array的記憶體配置模式。

一、通過getsizeof()計算資料行表的增長模式step1

sys.getsizeof()可以獲得列表所佔用的記憶體大小。請編寫程式計算一個長度為10000的列表,它的每個下標都儲存列表增長到此下標時的大小:

import sys# 【你的程式】計算size列表,它的每個小標都儲存增長到此下標時size列表的大小size = []for i in range(10000):    size.append(sys.getsizeof(size))import pylab as plpl.plot(size, lw=2, c=‘b‘)pl.show()

圖中每個階梯跳變的位置都表示一次記憶體配置,而每個階梯的長度表示記憶體配置多出來的大小。 

 

step2

請編寫程式計算表示每次分配記憶體時列表的記憶體大小的resize_pos數組:

import numpy as np#【你的程式】計算resize_pos,它的每個元素是size中每次分配記憶體的位置# 可以使用NumPy的diff()、where()、nonzero()快速完成此計算。size = []for i in range(10000):    size.append(sys.getsizeof(size))size = np.array(size)new_size = np.diff(size)resize_pos = size[np.where(new_size)]# resize_pos = size[np.nonzero(new_size)]pl.plot(resize_pos, lw=2)pl.show()print ("list increase rate:")tmp = resize_pos[25:].astype(np.float)  # ?print (np.average(tmp[1:]/tmp[:-1]))  # ?

由圖可知曲線呈指數增長,第45次分配記憶體時,列表的大小已經接近10000。 

?為了計算增長率,只需要計算resize_pos數組前後兩個值的商的平均值即可。

?為了提高精度,我們只計算後半部分的平均值,注意需要用astype()方法將整數數群組轉換為浮點數數組。程式的輸出如下:

list increase rate:

    1.12754776209

【注】np.where索引定位的兩種用法,np.nonzero非零值bool判斷的用法,np.diff差分函數的用法。

 

step3

我們可以用scipy.optimize.curve_fit()對resize_pos數組進行擬合,擬合函數為指數函數:

請編寫程式用上面的公式對resize_pos數組進行擬合:

from scipy.optimize import curve_fit#【你的程式】用指數函數對resize_pos數組進行擬合def func(x, a, b, c, d):      return a * np.exp(b * x + c) + dxdata = range(len(resize_pos))ydata = resize_pospopt, pcov = curve_fit(func, xdata, ydata) y = [func(i, *popt) for i in xdata]pl.plot(xdata, y, lw=1, c=‘r‘)pl.plot(xdata, ydata, lw=1, c=‘b‘)pl.show()print ("list increase rate by curve_fit:")print (10**popt[1])

 

list increase rate by curve_fit:    1.31158606108

【注意】本程式中對於scipy中的指數擬合做了示範。

 

 二、通過運算時間估算array記憶體配置情況

遺憾的是,無論array對象的長度是多少,sys.getsizeof()的結果都不變。因此無法用上節的方法計算array對象的增長因子。

由於記憶體配置時會耗費比較長的時間,因此可以通過測量每次增加元素的時間,找到記憶體配置時的長度。請編寫測量增加元素的時間的程式:

from array import arrayimport time#【你的程式】計算往array中添加元素的時間timestimes = []times_step = []arrays = [array(‘l‘) for i in range(1000)]start = time.time()for i in range(1000):    start_step = time.time()    [a.append(i) for a in arrays]    end = time.time()    times_step.append(end-start_step)    times.append(end-start)pl.figure()pl.plot(times)pl.figure()pl.plot(times_step)pl.show()

 輸出兩幅圖,前面的表示元素個數對應的程式總耗時,後面的表示每一次添加元素這一過程的耗時,注意,這張圖只有在array數量較大時才是這個形狀,數組數量不夠時折線圖差異很大。

 

 

進一步的,我們分析一下耗時顯著大於附近點(極大值)的時刻的序列對應此時元素數量的折線圖。

ts = np.array(times_step)le = range(np.sum(ts>0.00025))si = np.squeeze(np.where(ts>0.00025))pl.plot(le,si,lw=2)pl.show()

 

 

『Python』記憶體分析_list和array的記憶體增長模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.