目錄
一、理論
1.Python垃圾回收機制
一、理論
1.Python垃圾回收機制
(1)引?計數器
1)環狀雙向鏈表 refchain
在python程序中創建的任何對象都會放在refchain鏈表中。
name = "david"
age = 20
hobby = ["籃球",'游泳']
內部會創建?些數據【 上?個對象、下?個對象、類型、引?個數 】
name = "david"
new = name內部會創建?些數據【 上?個對象、下?個對象、類型、引?個數、val=18】
age = 20內部會創建?些數據【 上?個對象、下?個對象、類型、引?個數、items=元素、元素個數 】
hobby = ["籃球",'游泳']
在C源碼中如何體現每個對象中都有的相同的值:PyObject結構體(4個值)。
有多個元素組成的對象:PyObject結構體(4個值) + ob_size 。
2)類型封裝結構體
data = 3.14內部會創建:_ob_next = refchain中的上?個對象_ob_prev = refchain中的下?個對象ob_refcnt = 1ob_type = floatob_fval = 3.14
3)引?計數器
v1 = 3.14
v2 = 999
v3 = (1,2,3)
當python程序運?時,會根據數據類型的不同找到其對應的結構體,根據結構體中的字段來進?創建相 關的數據,然后將對象添加到refchain雙線鏈表中。 在C源碼中有兩個關鍵的結構體:PyObject、PyVarObject。 每個對象中有 ob_refcnt就是引?計數器,值默認為 1 ,當有其他變量引?對象時,引?計數器就會發 ?變化。
#引?
a = 777
b = a#刪除引?
a = 777
b = a
del b # b變量刪除;b對應對象引?計數器-1
del a # a變量刪除;a對應對象引?計數器-1
# 當?個對象的引?計數器為0時,意味著沒有?再使?這個對象了,這個對象就是垃圾,垃圾回收。
# 回收:1.對象從refchain鏈表移除;2.將對象銷毀,內存歸還。
4)循環引?問題
v1 = [11,22,33] #refchain中創建一個列表對象,由于v1=對象,所以列表引用對象計數器為1
v2 = [44,55,66] #refchain中創建一個列表對象,由于v2=對象,所以列表引用對象計數器為1
v1.append(v2) #把v2追加到v1中,則v2對應的[44,55,66]對象的引用計數器增加1,最終為2
v2.append(v1) #把v1追加到v2中,則v1對應的[11,22,33]對象的引用計數器增加1,最終為2del v1 #引用計數器-1
del v2 #引用計數器-1
(2)標記清除
?的:為了解決引?計數器循環引?的不?。
實現:在python的底層再維護?個鏈表,鏈表中專?放那些可能存在循環引?的對象
(list/tuple/dict/set)。
在Python內部 某種情況 下觸發,回去掃描 可能存在循環應?的鏈表 中的每個元素,檢查是否有循環引?,如果有則讓雙?的引?計數器 -1 ;如果是0則垃圾回收。
(3)分代回收
將可能存在循環應?的對象維護成3個鏈表:
0代:0代中對象個數達到700個掃描?次。
1代:0代掃描10次,則1代掃描?次。
2代:1代掃描10次,則2代掃描?次。
(4) 總結
在python中維護了?個refchain的雙向環狀鏈表,這個鏈表中存儲程序創建的所有對象,每種類型的對
象中都有?個ob_refcnt引?計數器的值,引?個數 + 1、-1 ,最后當引?計數器變為0時會進?垃圾回
收(對象銷毀、refchain中移除)。但是,在python中對于那些可以有多個元素組成的對象可能會存在循環引?的問題,為了解決這個問題
python?引?了標記清除和分代回收,在其內部為了4個鏈表,
refchain
2代,10?
1代,10次
0代,700個在源碼內部當達到各?的閾值時,就會觸發掃描鏈表進?標記清除的動作(有循環則各?-1)。