Python 專家解讀垃圾回收

貧而懶惰乃真窮,賤而無志乃真賤。——羅丹

  1. 前言

我們前兩篇文章講了 Python 的垃圾回收機制,但是沒有說什麼時候觸發垃圾回收機制,那麼這篇文章就來聊聊這個話題:Python 中的 GC 閾值和弱代假說。

  1. GC 閾值

Python 什麼時候會進行這個標記過程?隨着你的程序運行,Python 解釋器保持對新創建的對象,以及因爲引用計數爲零而被釋放掉的對象的追蹤。從理論上說,這兩個值應該保持一致,因爲程序新建的每個對象都應該最終被釋放掉。

當然,事實並非如此。因爲循環引用的原因,並且因爲你的程序使用了一些比其他對象存在時間更長的對象,從而被分配對象的計數值與被釋放對象的計數值之間的差異在逐漸增長。一旦這個差異累計超過某個閾值,則 Python 的收集機制就啓動了,並且觸發上邊所說到的零代算法,釋放 “浮動的垃圾”,並且將剩下的對象移動到一代列表。

隨着時間的推移,程序所使用的對象逐漸從零代列表移動到一代列表。而 Python 對於一代列表中對象的處理遵循同樣的方法,一旦被分配計數值與被釋放計數值累計到達一定閾值,Python 會將剩下的活躍對象移動到二代列表。

通過這種方法,你的代碼所長期使用的對象,那些你的代碼持續訪問的活躍對象,會從零代鏈表轉移到一代再轉移到二代。通過不同的閾值設置,Python 可以在不同的時間間隔處理這些對象。Python 處理零代最爲頻繁,其次是一代然後纔是二代。

  1. 弱代假說

來看看代垃圾回收算法的核心行爲:垃圾回收器會更頻繁的處理新對象。一個新的對象即是你的程序剛剛創建的,而一個來的對象則是經過了幾個時間週期之後仍然存在的對象。Python 會在當一個對象從零代移動到一代,或是從一代移動到二代的過程中提升 (promote) 這個對象。

爲什麼要這麼做?這種算法的根源來自於弱代假說 (weak generational hypothesis)。這個假說由兩個觀點構成:首先是年親的對象通常死得也快,而老對象則很有可能存活更長的時間。

假定現在我用 Python 創建一個新對象:

根據假說,我的代碼很可能僅僅會使用 ABC 很短的時間。這個對象也許僅僅只是一個方法中的中間結果,並且隨着方法的返回這個對象就將變成垃圾了。大部分的新對象都是如此般地很快變成垃圾。然而,偶爾程序會創建一些很重要的,存活時間比較長的對象 - 例如 web 應用中的 session 變量或是配置項。

通過頻繁的處理零代鏈表中的新對象,Python 的垃圾收集器將把時間花在更有意義的地方:它處理那些很快就可能變成垃圾的新對象。同時只在很少的時候,當滿足閾值的條件,收集器纔回去處理那些老變量。

  1. 小結

今天基本上全是文字描述,希望大家耐心看完之後有收穫,至此 Python 垃圾回收系列文章就到這裏結束了,謝謝大家的支持和陪伴,下篇文章再見。

  1. 關注公衆號

  微信公衆號:堆棧 future

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/zaDyHSGqjm4sQ86jf6y6Sg