文章地址:https://htmonster.xyz/blog/post/python_gc/
概要
- 引用計數爲主
- 標記-清除和分代收集爲輔
GC系統職責
- 爲新生對象分配內存
- 識別垃圾對象並回收
引用計數機制
-
Pyobject結構體(C語言) ob_refcnt 引用計數
-
操作
-
新引用:計數增加
-
解除引用:計數減小
-
引用爲0:刪除
優點 缺點 簡單 消耗資源【引用計數】 實時性:無引用 立馬刪除 循環引用 內存分擔
-
標記-清除算法
- 能夠引用其他對象的對象稱爲容器
- 容器間才能形成循環引用
- 將每個容器鏈接到雙向鏈表中
- 對於每個容器對象,設置一個gc_refs值,將其初始化爲對象的引用計數值
- 找對象容器,找到引用的對象,將其引用值減1
- 遍歷所有後,gc_refs值大於0的對象{存在非循環引用},放在另一個集合
- 釋放剩下的對象{無法到達的對象}
分代回收
-
所有對象依據“生存時間” 分爲3代
-
0代:新創建的對象 【經過一次 垃圾回收後 放入1代】
-
1代: 經過一次垃圾回收後 仍然存在 放入2代
-
2代:垃圾回收
-
-
回收頻率
-
觸發垃圾回收的條件
- 到達垃圾回收閾值,python虛擬機執行
- 手動調用gc.collect()
- python虛擬機退出時
gc 模塊
-
python標準庫
-
提供垃圾回收接口
#開啓關閉與判斷開啓結束狀態 gc.enable() gc.disable() gc.isenable() #執行垃圾回收 gc.collection() #設計及獲取閾值 gc.set_threshold() gc.get_threshold() #返回被垃圾回收器管理的對象 gc.get_objects() #獲得對象直接指向的對象 gc.get_referents(*obj) gc.get_referrers(*obj) #設置調試模式 gc.set_debug(flags)
內存泄露
- 情況一:對象被另一個生命週期特別長的對象所引用
- 例如:網絡服務器 單例模式 一個鏈接不再使用後 沒有進行刪除
- 情況二:循環引用的對象定義了
__del__
函數