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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

GC算法-标记清除算法

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

概述

標記清除算法, 描述起來很簡單, 從名字上就能看出, 分為兩個階段:

  • 標記階段: 遍歷所有對象, 將活動對象都打上標記
  • 清除階段: 遍歷堆, 將沒有標記的對象釋放掉.
  • 介紹完畢, 本文結束. 開玩笑, 確實看上去很簡單啦. 那就具體思考一下實現吧.

    實現

    介紹寫的很清楚了, 實現也是兩個階段唄, 先打tag, 后清除.

    標記

    尋找所有的活動對象, 要從一個起點開始, 根集合(包括棧、常量池等等), 然后一層一層找下去. 簡單來說就像這樣:

    add_mark(obj){// 防止重復標記if(obj.mark == true) return;obj.mark = true// 遍歷所有子對象for(o in objs){add_mark(o)} }

    將根基合的所有對象都調用一遍, 標記完成.

    清除

    標記時遍歷的是活動對象, 清除階段呢? 遍歷堆. 將堆上所有非活動對象清除. 就比如:

    當然, 其中的free函數也不是簡單的將地址回收, 而是將其記錄到一個鏈表中, 以方便下次申請內存. 實現大概如下:

    free(p){// 這里有一個全局變量, 保存鏈表頭: FREE_HEAD// 若當前對象和上一次回收的對象是連續內存, 直接合并if(FREE_HEAD + FREE_HEAD.size == p){FREE_HEAD.size += p.size}else{p.next = FREE_HEADFREE_HEAD = p} }

    這樣, 申請內存時遍歷FREE_HEAD, 找到大小合適的分塊. 若沒有找到, 就動態擴容咯. 這里其實還有一個優化的小方向, 開始的時候忘記了. 為了提高查找內存時速度, 可以將空閑鏈表按照大小進行區分, 這樣, 需要多大的內存, 直接到對應的鏈表中找就行了.

    雖然實現寫的很粗糙, 但大致意思有了.

    問題

    1.內存的碎片化

    從上面可以看到, 只對內存進行了清除, 但是沒有整理. 而內存的申請有事動態的, 就會導致出現很多離散的小片空閑內存. 極端情況甚至可能內存中還有200mb的空閑內存, 但是申請個10kb的空間卻找不到.

    2.暫停時間長

    其暫停時間與堆的大小成正比, 堆越大, 遍歷清除耗費的時間就越久.

    為了解決標記清除算法的問題, 衍生出了位圖標記法, BiBOP法 ,延遲清除算法等等個人感覺很雞肋(好吧, 或許是我未得其精髓).


    為了解決標記清除的問題, 有衍生出了 標記復制 , 標記整理 算法, 之后再議.

    總結

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

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