GC演算法 複製演算法

2021-10-04 19:24:32 字數 1680 閱讀 3565

複製演算法就是將記憶體空間二等分, 每次只使用其中一塊. 當執行gc時, 講a部分的所有活動物件集體移到b中, 就可以講a全部釋放.

畫個圖就是:

​ 在執行gc前, 記憶體長這樣:

​ 當執行gc後, 記憶體就變成這樣了:

還記得標記清除演算法的問題是什麼嗎? 記憶體碎片化嚴重. 現在好了, 碎片化問題解決了, 每次gc執行後, 記憶體空間都是連續的啦.

想一想gc執行的步驟是什麼? 很簡單啊, 遍歷所有可訪問的物件, 將所有物件的複製到另一塊記憶體中. 完畢.

遍歷所有根集合的物件, 跳過. 將每個物件都呼叫一次copy函式, 那麼, 這個copy函式如何實現呢?

function copy

(obj)

// 這裡假設有乙個全域性變數 addr 指向空閒記憶體的首位址

// 這裡直接將 obj的size大小複製到addr的地方

copy_data

(addr, obj, obj.size)

;// 記錄複製

obj.iscopy = true;

obj.newaddr = addr;

// 更新空閒位址

addr +

= size;

// 將所有子物件複製

for(child in children)

return obj.newaddr;

}

將所有根集合中的物件依次呼叫copy函式, 完成複製.

複製演算法分配新的物件變簡單了, 有沒有? 因為位址都是連續的, 所以申請新的位址也不用遍歷鍊錶等一堆操作, 直接按著位址劃分空間就行了.

很明顯,複製演算法解決了標記清除的乙個大問題, 記憶體碎片化嚴重. 在這裡, 根本不存在碎片化問題的好嘛. 其相比標記清除的優勢還是有一些的:

記憶體不會發生碎片化最大暫停時間更短:複製演算法只需要遍歷所有的活動物件, 而不需要遍歷堆, 比標記清除要少乙個堆的遍歷, 故而執行更快.

記憶體分配高效:標記清除是怎麼分配記憶體的? 通過乙個空閒位址的鍊錶, 然後挨個找. 而複製演算法將所有可分配的記憶體都放到一起了, 直接切割即可.

更好的區域性訪問:複製演算法複製後將物件與子物件放到一起, 這樣快取在讀取的時候就能夠一起讀取, 防止多次讀取資料.

當然, 缺點也很明顯. 將堆一分為二, 使用效率急速下滑.

堆的使用效率低, 只有1/2

頻繁的遞迴呼叫函式. 對棧的壓力比較大, 但是我們都知道, 所有用遞迴能寫的都可以換成迴圈來實現, 所以個人感覺這個並不是問題.

我看到有一種多空間複製演算法, 為了提高堆的使用效率. 將堆空間分成n份, 其中的兩份使用複製演算法, 剩餘的使用其他方法執行gc. 我實在是沒有明白這麼做的好處在哪…

GC複製演算法

gc複製演算法 它是把某一空間的活動物件全部複製到另乙個空間,複製完成後gc也就結束了 一起看下gc複製演算法的copying函式 copying copy函式在複製時會先檢查是否已被複製,若已被複製,不再操作,否則進行複製,貼上copied標籤複製完成返回新空間的位址,這樣即使有多個物件引用obj...

GC演算法 筆記 GC標記 壓縮演算法

將 gc標記 清除演算法與gc複製演算法相結合。一 lisp2演算法 標記階段結束後進入壓縮階段,壓縮階段縮小被標記節點之間的距離。compaction phase set forwarding ptr adjust ptr move obj 優點 可有效利用堆 缺點 壓縮花費計算成本 二 two ...

GC常用演算法

jvm在進行gc時,並不是對這三個區域統 一 大部分時候,都是新生代 新生代 倖存區 form,to 老年區 gc兩種類 輕gc 普通的gc 重gc 全域性gc 倖存區的from和to是動態變化的,誰空誰是to gc常用演算法 引用計數器演算法 原理 此物件有乙個引用,則 1 刪除乙個引用,則 1。...