深入探究Lua的GC算法(上)-《Lua設計與實現》


對於內存的管理,是程序在應用的時候的必需知識點,《Lua設計與實現》中對Lua語言的GC原理做了一個詳細的講解,雲風的blog也對其進行了詳盡的講解Lua GC 的源碼剖析 系列
給出作者 codedump 在github上的lua源碼鏈接:https://github.com/lichuang/Lua-5.1.4-codedump
這兒就繼續做《Lua設計與實現》的閱讀筆記,對Lua GC原理及其過程做一個詳盡的講解,由於篇幅較大,就一分為二,寫上下篇來講解整個過程。
 
一、GC的原理及其算法設計
不同的語言,對GC算法的設計不同,常見的GC算法是引用計數和Mark-Sweep算法, c#采用的是Mark-sweep && compact算法, Lua采用的是Mark-sweep算法,分開說一下:
引用計數算法:在一個對象被引用的情況下,將其引用計數加1,反之則減1,如果計數值為0,則在GC的時候回收,這個算法有個問題就是循環引用。
Mark-sweep算法:每次GC的時候,對所有對象進行一次掃描,如果該對象不存在引用,則被回收,反之則保存。
在Lua5.0及其更早的版本中,Lua的GC是一次性不可被打斷的過程,使用的Mark算法是雙色標記算法(Two color mark),這樣系統中對象的非黑即白,要么被引用,要么不被引用,這會帶來一個問題:在GC的過程中如果新加入對象,這時候新加入的對象無論怎么設置都會帶來問題,如果設置為白色,則如果處於回收階段,則該對象會在沒有遍歷其關聯對象的情況下被回收;如果標記為黑色,那么沒有被掃描就被標記為不可回收,是不正確的。
 
為了降低一次性回收帶來的性能問題以及雙色算法的問題,在Lua5.1后,Lua都采用分布回收以及三色增量標記清除算法(Tri-color incremental mark and sweep)
 
其基本的原理偽代碼,參考書中原文為:
每個新創建的對象顏色設置為白色
//初始化階段
遍歷root節點中引用的對象,從白色置為灰色,並且放入到灰色節點列表中
//標記階段
while(灰色鏈表中還有未掃描的元素):
從中取出一個對象,將其置為黑色
遍歷這個對象關聯的其他所有對象:
if 為白色
標記為灰色,加入到灰色鏈表中(insert to the head)
 
//回收階段
遍歷所有對象:
if 為白色,
沒有被引用的對象,執行回收
else
重新塞入到對象鏈表中,等待下一輪GC

 

二、GC的數據結構
分析Lua中對於需要GC的類型數據
#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
都會有一個基本的定義CommonHeader,其定義為:
 
next: GCObject鏈表指針,該指針用來將所有的GC對象都鏈接在一個表中;
tt: 數據類型:nil, boolean, number, string...
marked: 標記字段,byte表示的字段顏色定義為
這兒特定解釋一下為什么會有兩種白色,前面提到,5.1后的Lua采用的是三色標記算法,其實質是四色標記算法,分為0型白色和1型白色,在GC回收的時候,會設置當前的白色為其中一種,詳見globalstate中的currentwhite,這樣在代碼回收的時候,如果當前對象的白色不為currentwhite,則認為其不可回收,這樣的對象需要等到下一次的GC才能決定是否回收,具體參看后面的,會有對應的應用。對於global_state的設計為:
具體的參數的作用,詳見注釋,就不在一一解釋了
 
三、GC的流程
1、數據的創建
想要了解GC的過程,首先看看數據是怎么在創建的時候被鏈接到GC鏈表中的,主要分為三種數據的創建
1) 一般數據的創建 luaC_link
 
簡單直接,直接insert to the head
2) upval的創建 luaC_linkupval
3) userdata(udata)的創建 luaS_newdata
 
2、開始GC
整個GC過程分為五個階段,其定義為
其執行GC的函數為singlestep,來看第一步的操作:
進一步看看markroot的操作:
 
其實就是reset一遍相關的變量,然后標記mainthread, G表,registry表,然后切換到下一個標記階段。
參看定義:
 
最后都要執行reallymarkobject函數(此處需要展示一下我的豎屏截圖便利了:D):
 
基本的注釋都解釋了各個對象是如何的處理的,udata是不會引用其他類型的數據,所以一步到黑色,upvalue則根據是否為close來決定是否標記到黑色,open狀態的upvalue變化較為頻繁,需要在后面的remarkupvals中解決。
寫到這兒,已經寫很長了,為了閱讀的便利,讓我們下一篇文章繼續GC的進程吧:D


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM