日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

GC算法-复制算法

發布時間:2024/8/23 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GC算法-复制算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概述

復制算法就是將內存空間二等分, 每次只使用其中一塊. 當執行GC時, 講A部分的所有活動對象集體移到B中, 就可以講A全部釋放.

畫個圖就是:

? 在執行GC前, 內存長這樣:

? 當執行GC后, 內存就變成這樣了:

還記得標記清除算法的問題是什么嗎? 內存碎片化嚴重. 現在好了, 碎片化問題解決了, 每次GC執行后, 內存空間都是連續的啦.

實現

想一想GC執行的步驟是什么? 很簡單啊, 遍歷所有可訪問的對象, 將所有對象的復制到另一塊內存中. 完畢.

遍歷所有根集合的對象, 跳過. 將每個對象都調用一次copy函數, 那么, 這個copy函數如何實現呢?

function copy(obj){// 若對象已經被復制過了, 則將其直接返回if(obj.isCopy == true){// 在原來對象中保存一下新的地址, 方便返回return obj.newAddr; }// 這里假設有一個全局變量 ADDR 指向空閑內存的首地址// 這里直接將 obj的size大小復制到ADDR的地方copy_data(ADDR, obj, obj.size);// 記錄復制obj.isCopy = true;obj.newAddr = ADDR;// 更新空閑地址ADDR += size;// 將所有子對象復制for(child in children){child = copy(child);}return obj.newAddr; }

將所有根集合中的對象依次調用copy函數, 完成復制.

復制算法分配新的對象變簡單了, 有沒有? 因為地址都是連續的, 所以申請新的地址也不用遍歷鏈表等一堆操作, 直接按著地址劃分空間就行了.

分析

很明顯, 復制算法解決了標記清除的一個大問題, 內存碎片化嚴重. 在這里, 根本不存在碎片化問題的好嘛. 其相比標記清除的優勢還是有一些的:

  • 內存不會發生碎片化
  • 最大暫停時間更短: 復制算法只需要遍歷所有的活動對象, 而不需要遍歷堆, 比標記清除要少一個堆的遍歷, 故而執行更快.
  • 內存分配高效: 標記清除是怎么分配內存的? 通過一個空閑地址的鏈表, 然后挨個找. 而復制算法將所有可分配的內存都放到一起了, 直接切割即可.
  • 更好的局部訪問: 復制算法復制后將對象與子對象放到一起, 這樣緩存在讀取的時候就能夠一起讀取, 防止多次讀取數據.
  • 當然, 缺點也很明顯. 將堆一分為二, 使用效率急速下滑.

  • 堆的使用效率低, 只有1/2
  • 頻繁的遞歸調用函數. 對棧的壓力比較大, 但是我們都知道, 所有用遞歸能寫的都可以換成循環來實現, 所以個人感覺這個并不是問題.
  • 我看到有一種多空間復制算法, 為了提高堆的使用效率. 將堆空間分成N份, 其中的兩份使用復制算法, 剩余的使用其他方法執行GC. 我實在是沒有明白這么做的好處在哪…

    總結

    以上是生活随笔為你收集整理的GC算法-复制算法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。