垃圾回收算法對比

垃圾回收GC的全拼是 Garbage Collection 其在維基百科的定義是: 在計算機科學中,垃圾回收(英語:Garbage Collection,縮寫爲GC)是一種自動的內存管理機制。當一個電腦上的動態內存不再需要時,就應該予以釋放,以讓出內存,這種內存資源管理,稱爲垃圾回收(garbage collection)

垃圾回收算法有多種,先看看幾個評價垃圾回收算法性能的幾個方面,再具體看看各種算法的優缺點

  • 吞吐量 throughput
  • 最大暫停時間
  • 堆使用效率
  • 訪問的局部性

一、 標記-清除算法 Mark-Sweep GC

如字面意思 mark-sweep 分爲兩個階段:

  1. 標記階段:從根集合出發,將所有活動對象及其子對象打上標記
  2. 清除階段:遍歷堆,將非活動對象(未打上標記)的連接到空閒鏈表上

優點

實現簡單, 容易和其他算法組合

缺點

  • 碎片化, 會導致無數小分塊散落在堆的各處
  • 分配速度不理想,每次分配都需要遍歷空閒列表找到足夠大的分塊
  • 與寫時複製技術不兼容,因爲每次都會在活動對象上打上標記

二、標記-壓縮 Mark-Compact

和“標記-清除”相似,不過在標記階段後它將所有活動對象緊密的排在堆的一側(壓縮),消除了內存碎片, 不過壓縮是需要花費計算成本的。標記後需要定位各個活動對象的新內存地址,然後再移動對象,總共搜索了3次堆。

優點

有效利用了堆,不會出現內存碎片 也不會像複製算法那樣只能利用堆的一部分

缺點

壓縮過程的開銷,需要多次搜索堆

三、引用計數 Reference Counting

引用計數,就是記錄每個對象被引用的次數,每次新建對象、賦值引用和刪除引用的同時更新計數器,如果計數器值爲0則直接回收內存。 很明顯,引用計數最大的優勢是暫停時間短。

優點

  • 可即刻回收垃圾
  • 最大暫停時間短
  • 沒有必要沿指針查找, 不要和標記-清除算法一樣沿着根集合開始查找

缺點

  • 計數器的增減處理繁重
  • 計數器需要佔用很多位
  • 實現繁瑣複雜, 每個賦值操作都得替換成引用更新操作
  • 循環引用無法回收

四、GC 複製算法

將堆分爲兩個大小相同的空間 From 和 To, 利用 From 空間進行分配,當 From 空間滿的時候,GC將其中的活動對象複製到 To 空間,之後將兩個空間互換即完成GC。

優點

  • 優秀的吞吐量, 只需要關心活動對象
  • 可實現高速分配; 因爲分塊是連續的,不需要使用空閒鏈表
  • 不會發生碎片化
  • 與緩存兼容

缺點

  • 堆使用率低
  • 與保守式GC不兼容
  • 遞歸調用函數, 複製子對象需要遞歸調用複製函數 消耗棧

五、 保守式GC

根空間有以下幾種:

  • 寄存器
  • 調用棧
  • 全局變量空間

但這些都是不明確的根, 因爲調用棧裏邊的調用幀(call frame) 既有指針也有非指針(值類型)

保守式GC檢查不明確根的基本項目:

  1. 是不是被正確對齊的值?(在32位cpu的情況下,爲4的倍數)
  2. 是不是指針堆內?
  3. 是不是指着對象的開頭?
  4. 有種情況是,非指正和堆裏的對象地址一樣;這時保守式GC “把可以的東西看做指針,穩妥處理”

優點

GC不依賴於語言處理程序

缺點

  • 識別指針和非指針需要成本
  • 錯誤識別指針會壓迫堆; 可能錯將非指針當做指針,然後將其作爲內存地址使得對應堆中的死對象當做活對象
  • 能夠使用的gc算法有限; 不能使用複製算法這類移動對象的gc算法

準確式GC
需要依賴 “語言處理程序的支援”,能基於能精確識別指針和非指針的“正確根”來執行gc

六、分代回收

出發點:大部分對象生成後馬上就變成垃圾,很少有對象能活的很久

  • 新生代 = 生成空間 + 2 * 倖存區 複製算法
  • 老年代 標記-清除算法

對象在生成空間創建,當生成空間滿之後進行 minor gc,將活動對象複製到第一個倖存區,並增加其“年齡” age,當這個倖存區滿之後再將此次生成空間和這個倖存區的活動對象複製到另一個倖存區,如此反覆,當活動對象的 age 達到一定次數後將其移動到老年代; 當老年代滿的時候就用標記-清除或標記-壓縮算法進行major gc

吞吐量得到改善, 分代垃圾回收花費的時間是GC複製算法的四分之一;但是如果部分程序新生成對象存活很久的話分代回收會適得其反

七、增量式GC

本來gc只是默默的在幕後回收資源的,但是如果gc任務繁重則會長時間暫停應用程序的執行, 增量式gc就是一種逐漸推進垃圾回收來控制mutator最大暫停時間的方法

三色標記算法

白色: 還未搜索過的對象
灰色: 正在搜索的對象
黑色: 搜索完成的對象

根查找階段: 對能直接從根引用的對象打上標記,堆放到標記棧裏(白色 塗成 灰色)

標記階段: 從標記棧中取出對象,將其子對象塗成灰色;這個階段不是一下子處理所有的灰色對象,而只是處理一定個數,然後暫停gc

清除階段: 將沒被標記的白色對象連接到空閒鏈表,並重置已標記的對象標記位

優點

縮短最大暫停時間

缺點

降低了吞吐量

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章