如何手動釋放Python的內存

版權聲明:本文爲博主原創文章,可以轉載但必須註明出處。    https://blog.csdn.net/nirendao/article/details/44426201
在上篇博客中,提到了對一個腳本進行的多次優化。當時以爲已經優化得差不多了,但是當測試人員測試時,我才發現,踩到了Python的一個大坑。

在上文的優化中,對每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中可以明顯看出。
--------------------- 
作者:執假以爲真 
來源:CSDN 
原文:https://blog.csdn.net/nirendao/article/details/44426201/ 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章