時間基準垃圾回收(Time-based GC)原理與設計詳解
1. 記憶體管理三大流派
- MRC (Manual Reference Counting):手動
retain/release/autorelease,程式設計師自管生命週期
- 自動垃圾回收 (GC):執行期自動識別並回收不可達物件
- ARC (Automatic Reference Counting):介於 MRC 與 GC 之間,編譯器自動插入保留/釋放,但無法處理循環引用(retain cycles),需程式設計師自行斷開
2. 三大基礎 GC 演算法
2.1 引用計數法
每個物件維護計數器,引用+1,釋放-1,歸零即回收。
- 優點:簡單、無執行期支援、物件即時釋放、無額外暫停
- 缺點:無法處理循環引用;多執行緒需加鎖同步,影響效能
應用:Apple ARC、C++ std::shared_ptr
2.2 標記-清除法
記憶體耗盡時,從 GC Roots 遍歷物件圖,標記可達物件,清除未標記物件。
- 優點:解決循環引用、平時不影響程式效能
- 缺點:GC 時需暫停程式(Stop-the-World),大記憶體/多物件時暫停時間長;產生記憶體碎片
2.3 複製法 / 分代收集
記憶體劃分為兩塊(From/To),分配在 From,滿時將存活物件複製到 To,角色互換。
- 優點:分配極快(指標碰撞)、無碎片、若存活物件少則 GC 暫停短
- 缺點:50% 記憶體浪費;與分頁/Cache 機制潛在衝突
分代假設:多數物件朝生夕死,少數物件長期存活。將堆劃分為新生代(Eden + Survivor)、老年代、永久代。新生代用複製法,老年代用標記-整理,提升整體 GC 效能。
3. Attilax Time-based GC 設計
傳統 GC 掃描整個堆,作者提出基於時間的增量式收集:
- GC 相關資料集中管理,收集過程不碰用戶資料塊
- 關鍵挑戰:關聯堆疊資料。C 語言無堆疊遍歷特性,需自然方案讓用戶標記堆疊變數
- 每個呼叫層級的臨時記憶體掛接在當前層級,函數返回時自動斷開;返回值需保留
- 需在每個函數入口/出口加入監護(C++ 可用 RAII guard 物件簡化),優化此監護過程為重點
4. GC 工作流程五步驟
- 標記:識別可達物件
- 計劃:決定回收策略
- 清理:釋放不可達物件
- 引用更新:修正移動物件後的引用
- 壓縮:整理記憶體碎片
5. 資源包裝策略
將 file、network socket 等外部資源包裝為 GC 可管理物件,確保記憶體回收時同步釋放系統資源,避免洩漏。
6. 參考資料
- 各程式語言 GC 演算法優劣分析 - 知乎
- JeffWong《垃圾回收機制 GC 知識再總結》- 博客園
- 《垃圾回收(GC)的三種基本方式》- 伯樂在線