python垃圾回收

引用計數

PyObject

python裏每一個東西都是對象,它們的核心就是一個結構體:PyObject

PyObject是每個對象必有的內容,其中ob_refcnt就是做爲引用計數。當一個對象有新的引用時,它的ob_refcnt就會增加,當引用它的變量被刪除,它的ob_refcnt就會減少

引用計數優缺點

優點 

1.簡單

2.實時,一旦沒有引用,內存就直接釋放了。不用像其他機制等到特定時機。實時性還帶來一個好處,處理回收內存的時間分攤到了運行時。

缺點

1.維護引用計數消耗資源,會造成循環引用導致無法回收,造成內存泄露

2.循環引用

list1 = [] 
list2 = [] 
list1.append(list2) 
list2.append(list1)

list1與list2相互引用,如果不存在其他對象對它們的引用,list1與list2的引用計數也仍然爲1,所佔用的內存永遠無法被回收,這將是致命的。

標記-清除

在Python中,所有能夠引用其他對象的對象都被稱爲容器(container)。因此只有容器之間纔可能形成循環引用。Python的垃圾回收機制利用了這個特點來尋找需要被釋放的對象。爲了記錄下所有的容器對象,Python將每一個 容器都鏈到了一個雙向鏈表中,之所以使用雙向鏈表是爲了方便快速的在容器集合中插入和刪除對象。有了這個維護了所有容器對象的雙向鏈表以後, Python在垃圾回收時使用如下步驟來尋找需要釋放的對象:

1.對於每一個容器對象, 設置一個gc_refs值, 並將其初始化爲該對象的引用計數值.

2.對於每一個容器對象, 找到所有其引用的對象, 將被引用對象的gc_refs值減1.

3.執行完步驟2以後所有gc_refs值還大於0的對象都被非容器對象引用着, 至少存在一個非循環引用. 因此不能釋放這些對象, 將他們放入另一個集合.

4.在步驟3中不能被釋放的對象, 如果他們引用着某個對象, 被引用的對象也是不能被釋放的, 因此將這些 對象也放入另一個集合中.

5.此時還剩下的對象都是無法到達的對象. 現在可以釋放這些對象了.

分代回收

分代技術簡單點說就是:對象存在時間越長,越可能不是垃圾,應該越少去收集。

1.Python將所有對象根據’生存時間’分爲3代, 從0到2.

2.所有新創建的對象都分配爲第0代.

3.當這些對象經過一次垃圾回收仍然存在則會被放入第1代中. 如果第1代中的對象在一次垃圾回收之後仍然存在則被放入第2代.

4.對於不同代的對象Python的回收的頻率也不一樣. 可以通過gc.set_threshold(threshold0[, threshold1[, threshold2]]) 來定義

5.當Python的垃圾回收器中新增的對象數量減去刪除的對象數量大於threshold0時, Python會對第0代對象 執行一次垃圾回收. 每當第0代被檢查的次數超過了threshold1時, 第1代對象就會被執行一次垃圾回收. 同理每當第1代被檢查的次數超過了threshold2時, 第2代對象也會被執行一次垃圾回收.

觸發垃圾回收的情況

在三種情況下會觸發垃圾回收:  

1.達到了垃圾回收的閾值,Python虛擬機自動執行

2.手動調用gc.collect()

3.Python虛擬機退出的時候

 

 

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