py

看板Marginalman作者 (溫水佳樹的兄長大人)時間1年前 (2024/11/16 14:49), 編輯推噓2(201)
留言3則, 3人參與, 1年前最新討論串15/16 (看更多)
因應上一篇提到的問題,Cpython還有兩種回收機制:標記與清除演算法與分代機制。 標記與清除演算法 首先,Cpython會創建一個紀錄可能需要回收物件的linked list,當物件被創造時, Cpython會判斷該物件的類型是否開啟GC功能,假如有GC功能,則放入該linked list。 PyTypeObject PyList_Type = { ... Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LIST_SUBCLASS | _Py_TPFLAGS_MATCH_SELF | Py_TPFLAGS_SEQUENCE, /* tp_flags */ ... }; 我們可以發現list有Py_TPFLAGS_HAVE_GC,所以當我們創建list類型的物件,此物件就會 被放入list。 另外,Cpython會在該物件上加上PyGC_Head,PyGC_Head包含兩個指標: prev指向前一個須追蹤物件,next指向下一個須追蹤物件 透過兩個指標,Cpython創造一個linked list追蹤可能需要回收的物件。 回收機制標記了可能需回收的物件,之後,它將物件區分為兩類: 可達(reachable)與不可達(unreachable) 可達是指有變數引用或有可達物件引用;不可達則無。 區分可達與不可達後,清除就是回收不可達物件。 分代機制 我們有了標記與清除演算法,我們可以設定每過一段時間就清除一次,但,每清除一次就 必須遍歷整個linked list,linked list裡面可能有一些長時間使用的東西,每次遍歷都 會掃到很多不需要清理的物件,所以,Cpython設計了分代機制。 分代機制就是將物件列表分成三代: 第零代:新物件被創造就放在這裡 第一代:第零代被清理後,活下來的物件移到這裡 第二代:第一代被清理後,活下來的物件移到這裡 再來討論何時回收這三代的物件 head前面我們提過了,每代還有threshold跟count threshold是每一代的閥值,count每代的意義不同,在第零代,count代表第零代列表的 物件數量,每次創建可能需回收物件,count += 1。 第一代count代表第零代的垃圾回收次數,第二代的Count代表第一代的垃圾回收次數 當count > threshold,該代就會執行垃圾回收。 每代的可能需要遍歷的最大數量如下: 第零代:generation[0].threshold 第一代:generation[0].threshold * generation[0].threshold(第零代全部存活) 第二代:無上限 所以,第二代可能囤積大量物件,所以,為了減少回收第二代的次數 Cpython對第二代回收加了個條件: 當第二代中等待第一次完全回收的物件數量/上次完全回收存活下來的物件數量 > 1/4 第二代才會執行垃圾回收 GC linked list 關於此linked list如何新增與刪除新物件的問題 其實它就跟一般linked list差不多 不贅述 參考資料: https://reurl.cc/jQMZd1 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 223.137.116.63 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Marginalman/M.1731739777.A.92E.html

11/16 14:52, 1年前 , 1F
大師
11/16 14:52, 1F

11/16 15:47, 1年前 , 2F

11/16 15:53, 1年前 , 3F
這個人好神
11/16 15:53, 3F
文章代碼(AID): #1dE421ak (Marginalman)
討論串 (同標題文章)
完整討論串 (本文為第 15 之 16 篇):
1
5
9月前, 03/09
2
3
1年前, 11/16
0
3
1年前, 11/12
2
2
1年前, 10/02
6
13
1
1
1年前, 09/28
1
1
2
6
0
6
1年前, 09/26
1
7
文章代碼(AID): #1dE421ak (Marginalman)