天天看點

python裡面的垃圾回收機制

Garbage collection(GC)

現在的進階語言如java,c#等,都采用了垃圾收集機制,而不再是c,c++裡使用者自己管理維護記憶體的方式。自己管理記憶體極其自由,可以任意申請記憶體,但如同一把雙刃劍,為大量記憶體洩露,懸空指針等bug埋下隐患。

對于一個字元串、清單、類甚至數值都是對象,且定位簡單易用的語言,自然不會讓使用者去處理如何配置設定回收記憶體的問題。

python裡也同java一樣采用了垃圾收集機制,不過不一樣的是:

python采用的是​

​引用計數​

​機制為主,​

​标記-清除​

​和​

​分代收集​

​兩種機制為輔的政策

GC系統所承擔的工作遠比“垃圾回收”多得多。它們負責三個重要任務:

  • 為新生成的對象配置設定記憶體
  • 識别那些垃圾對象
  • 從垃圾對象回收記憶體

  如果将應用程式比作人的身體:所有你所寫的那些優雅的代碼,業務邏輯,算法,應該就是大腦。垃圾回收就是應用程式那顆躍動的心。像心髒為身體其他器官提供血液和營養物那樣,垃圾回收器為你的應該程式提供記憶體和對象。如果垃圾回收器停止工作或運作遲緩,像動脈阻塞,你的應用程式效率也會下降,直至最終死掉。

gc子產品的自動垃圾回收機制

必須要import gc子產品,并且is_enable()=True才會啟動自動垃圾回收。

這個機制的主要作用就是發現并處理不可達的垃圾對象。

垃圾回收=垃圾檢查+垃圾回收      

1、引用計數機制:

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

​PyObject​

typedef struct_object {
int ob_refcnt; #引用計數
    struct_typeobject *ob_type;
} PyObject;

PyObject是每個對象必有的内容,其中ob_refcnt
就是做為引用計數。當一個對象有新的引用時,它的ob_refcnt
就會增加,當引用它的對象被删除,它的ob_refcnt
就會減少      
#define Py_INCREF(op)   ((op)->ob_refcnt++) //增加計數
#define Py_DECREF(op) \ //減少計數
    if (--(op)->ob_refcnt != 0) \
        ; \
    else \
        __Py_Dealloc((PyObject *)(op))      
import sys

class A(object):
     def __init__(self):
         """初始化對象"""
         print ('object born id:%s'%str(hex(id(self))))

def f1():
 """循環引用變量與删除變量"""
 while True:
     c1=A()
     del c1

def func(c):
 """getrefcount() 傳回對象的引用計數"""
 print ('object refcount is:',sys.getrefcount(c))

if __name__=='__main__':
     # 生成對象
     a=A()
     func(a)

    # 增強引用
     b=a
     func(a)

     # 銷毀引用
     del b
     func(a)



結果:
object born id:0x1043059b0
object refcount is: 4
object refcount is: 5
object refcount is: 4      

gc方式1:引用計數

若此對象無其他對象引用,則立馬回收掉

優點:簡單、實時(将處理垃圾時間分攤到運作代碼時,而不是等到一次回收)

缺點:

1.儲存對象引用數會占用一點點記憶體空間

2.每次執行語句都可能更新引用數,不再使用大的資料結構時,會引起大量對象被回收

3.不能處理循環引用的情況

gc方式2:标記-清除(Mark—Sweep)

此方式主要用來處理循環引用的情況,隻有容器對象(list、dict、tuple,instance)才會出現循環引用的情況

python裡面的垃圾回收機制
處理過程

1.将所有容器對象放到一個雙向連結清單中(連結清單為了友善插入删除),這些對象為0代

2.循環周遊連結清單,如果被本連結清單内的對象引入,自身的被引用數-1,如果被引用數為0,則觸發引用計數回收條件,被回收掉

3.未被回收的對象,更新為1代

『标記清除(Mark—Sweep)』算法是一種基于追蹤回收(tracing GC)技術實作的垃圾回收算法。它分為兩個階段:第一階段是标記階段,GC會把所有的『活動對象』打上标記,第二階段是把那些沒有标記的對象『非活動對象』進行回收。那麼GC又是如何判斷哪些是活動對象哪些是非活動對象的呢?

對象之間通過引用(指針)連在一起,構成一個有向圖,對象構成這個有向圖的節點,而引用關系構成這個有向圖的邊。從根對象(root object)出發,沿着有向邊周遊對象,可達的(reachable)對象标記為活動對象,不可達的對象就是要被清除的非活動對象。根對象就是全局變量、調用棧、寄存器。      

何時觸發

1.被引用為0時,立即回收目前對象

2.達到了垃圾回收的門檻值,觸發标記-清除

3.手動調用gc.collect()

4.Python虛拟機退出的時候

​​連結​​

​​python源碼解讀垃圾回收機制​​

​​python垃圾回收機制​​