手動釋放Python的記憶體的方法

高洛峰
發布: 2017-03-24 17:37:10
原創
6376 人瀏覽過

在上文的最佳化中,對每500個用戶,會進行一些計算並記錄結果在磁碟檔案中。原本以為這麼做,這些結果就在磁碟檔案中了,而不會再繼續佔用記憶體;但實際上,Python的大坑就是Python不會自動清理這些記憶體。這是由其本身實現決定的。具體原因網路上多有文章介紹,這裡就不copy了。
本篇將貼一個筆者的實驗腳本,用以說明Python確實存在這麼一個不釋放內存的現象,另外也提出一個解決方案,即:先del,再明確調用gc.collect(). 腳本和具體效果見下。
實驗環境一:Win 7, Python 2.7

from time import sleep, time 
import gc 
 
def mem(way=1): 
 print time() 
 for i in range(10000000): 
  if way == 1: 
   pass 
  else: # way 2, 3 
   del i 
    
 print time() 
 if way == 1 or way == 2: 
  pass 
 else: # way 3 
  gc.collect() 
 print time() 
   
if __name__ == "__main__": 
 print "Test way 1: just pass" 
 mem(way=1) 
 sleep(20) 
 print "Test way 2: just del" 
 mem(way=2) 
 sleep(20) 
 print "Test way 3: del, and then gc.collect()" 
 mem(way=3) 
 sleep(20)
登入後複製


運行結果如下:

Test way 1: just pass 
1426688589.47 
1426688590.25 
1426688590.25 
Test way 2: just del 
1426688610.25 
1426688611.05 
1426688611.05 
Test way 3: del, and then gc.collect() 
1426688631.05 
1426688631.85 
1426688631.95
登入後複製


對於way 1和way 2,結果是完全一樣的,程式記憶體消耗峰值是326772KB,在sleep 20秒時,記憶體即時消耗是244820KB;
對於way 3,程式記憶體消耗峰值同上,但是sleep時記憶體即時消耗就只有6336KB了。
實驗環境二: Ubuntu 14.10, Python 2.7.3
運行結果:

Test way 1: just pass 
1426689577.46 
1426689579.41 
1426689579.41 
Test way 2: just del 
1426689599.43 
1426689601.1 
1426689601.1 
Test way 3: del, and then gc.collect() 
1426689621.12 
1426689622.8 
1426689623.11
登入後複製
ubuntu@my_machine:~$ ps -aux | grep test_mem 
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html 
ubuntu 9122 10.0 6.0 270916 245564 pts/1 S+ 14:39 0:03 python test_mem.py 
ubuntu 9134 0.0 0.0 8104 924 pts/2 S+ 14:40 0:00 grep --color=auto test_mem 
ubuntu@my_machine:~$ ps -aux | grep test_mem 
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html 
ubuntu 9122 10.0 6.0 270916 245564 pts/1 S+ 14:39 0:03 python test_mem.py 
ubuntu 9134 0.0 0.0 8104 924 pts/2 S+ 14:40 0:00 grep --color=auto test_mem 
ubuntu@my_machine:~$ ps -aux | grep test_mem 
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html 
ubuntu 9122 11.6 0.1 30956 5608 pts/1 S+ 14:39 0:05 python test_mem.py
登入後複製


#結論:
以上說明,當呼叫del時,其實Python並不會真正release內存,而是將其繼續放在其內存池中;只有在顯式調用gc.collect()時,才會真正release內存。
進一步:
其實回到上一篇部落格的腳本中,也讓其引入gc.collect(),然後寫個監控腳本監控記憶體消耗:

while ((1)); do ps -aux | sort -n -k5,6 | grep my_script; free; sleep 5; done
登入後複製


結果發現:記憶體並不會在每500個使用者一組執行完後恢復,而是一直持續消耗到僅存約70MB時,gc才好像運作。在本環境中,機器使用的是Cloud instance,總記憶體2G,可用記憶體約為1G,本腳本記憶體常用消耗是900M - 1G。換句話說,對於這個腳本來說,gc並沒有立即起作用,而是當系統可用記憶體從1 - 1.2G下降到只剩下70M左右時,gc才開始發揮作用。這點確實比較奇怪,不知道和該腳本是在Thread中使用的gc.collect()是否有關,或者是gc發揮作用原本就不是可控的。作者尚未做相關實驗,可能會在下篇部落格中繼續探討。
但是,可以肯定的是,若不使用gc.collect(), 原始腳本將會將系統記憶體耗盡而被殺死。這一點從syslog中可以明顯看出。

以上是手動釋放Python的記憶體的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!