天天看點

101 python進階 - GC門檻值

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

當然,事實并非如此。因為循環引用的原因,并且因為你的程式使用了一些比其他對象存在時間更長的對象,進而被配置設定對象的計數值與被釋放對象的計數值之間的差異在逐漸增長。一旦這個差異累計超過某個門檻值,則Python的收集機制就啟動了,并且觸發上邊所說到的零代算法,釋放“浮動的垃圾”,并且将剩下的對象移動到一代清單。

随着時間的推移,程式所使用的對象逐漸從零代清單移動到一代清單。而Python對于一代清單中對象的處理遵循同樣的方法,一旦被配置設定計數值與被釋放計數值累計到達一定門檻值,Python會将剩下的活躍對象移動到二代清單。

通過這種方法,你的代碼所長期使用的對象,那些你的代碼持續通路的活躍對象,會從零代連結清單轉移到一代再轉移到二代。通過不同的門檻值設定,Python可以在不同的時間間隔處理這些對象。Python處理零代最為頻繁,其次是一代然後才是二代。

弱代假說

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

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

假定現在我用Python或是Ruby建立一個新對象:

101 python進階 - GC門檻值

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