gccollectpython
⑴ python如何讓程序一直運行且內存資源自動釋放
這當然是和代碼寫法有關,不貼出來就無法解決
⑵ python的內存管理機制
論壇
活動
招聘
專題
打開CSDN APP
Copyright © 1999-2020, CSDN.NET, All Rights Reserved
登錄
XCCS_澍
關注
Python 的內存管理機制及調優手段? 原創
2018-08-05 06:50:53
XCCS_澍
碼齡7年
關注
內存管理機制:引用計數、垃圾回收、內存池。
一、引用計數:
引用計數是一種非常高效的內存管理手段, 當一個 Python 對象被引用時其引用計數增加 1, 當其不再被一個變數引用時則計數減 1. 當引用計數等於 0 時對象被刪除。
二、垃圾回收 :
1. 引用計數
引用計數也是一種垃圾收集機制,而且也是一種最直觀,最簡單的垃圾收集技術。當 Python 的某個對象的引用計數降為 0 時,說明沒有任何引用指向該對象,該對象就成為要被回收的垃圾了。比如某個新建對象,它被分配給某個引用,對象的引用計數變為 1。如果引用被刪除,對象的引用計數為 0,那麼該對象就可以被垃圾回收。不過如果出現循環引用的話,引用計數機制就不再起有效的作用了
2. 標記清除
如果兩個對象的引用計數都為 1,但是僅僅存在他們之間的循環引用,那麼這兩個對象都是需要被回收的,也就是說,它們的引用計數雖然表現為非 0,但實際上有效的引用計數為 0。所以先將循環引用摘掉,就會得出這兩個對象的有效計數。
3. 分代回收
從前面「標記-清除」這樣的垃圾收集機制來看,這種垃圾收集機制所帶來的額外操作實際上與系統中總的內存塊的數量是相關的,當需要回收的內存塊越多時,垃圾檢測帶來的額外操作就越多,而垃圾回收帶來的額外操作就越少;反之,當需回收的內存塊越少時,垃圾檢測就將比垃圾回收帶來更少的額外操作。
⑶ 如何釋放Python佔用的內存
在上文的優化中,對每500個用戶,會進行一些計算並記錄結果在磁碟文件中。原本以為這么做,這些結果就在磁碟文件中了,而不會再繼續佔用內存;但實際上,python的大坑就是Python不會自動清理這些內存。這是由其本身實現決定的。具體原因網上多有文章介紹,這里就不了。
本篇博客將貼一個筆者的實驗腳本,用以說明Python確實存在這么一個不釋放內存的現象,另外也提出一個解決方案,即:先del,再顯式調用gc.collect(). 腳本和具體效果見下。
實驗環境一:Win 7, Python 2.7
[python] view plain
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)
運行結果如下:
[plain] view plain
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
運行結果:
[plain] view plain
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
[plain] view plain
ubuntu@my_machine:~$ ps -aux | grep test_mem
Warning: bad ps syntax, perhaps a bogus '-'? See
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
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
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(),然後寫個監控腳本監測內存消耗情況:
[plain] view plain
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的內存
象的引用計數減少;
函數運行結束,所有局部變數都被銷毀,對象的引用計數也就隨之減少。例如 foo(x) 運行結束,x 被銷毀;
當變數被賦值給另一個對象時,原對象的引用計數也會減少。例如 x = 4,這時候 3 這個對象的引用計數就減 1 了;
使用 del 刪除一個變數也會導致對象引用減少。例如 del x;
對象從集合對象中移除。例如 lst.remove(x);
包含對象的集合對象被銷毀。例如 del lst;
這些操作都可能使對象變成垃圾回收對象,由垃圾收集器負責收集,當然垃圾收集器也負責處理循環引用對象。
要立即釋放,可以使用下面的代碼
import gc
gc.collect()