深入理解瀏覽器垃圾回收機制(V8)

  • 定義
    棧用來在函數執行時存儲保存執行上下文環境,我們一般也稱調用棧,如基本類型的變量,引用類型的引用地址等都保存在棧中。執行到當前函數時進行入棧,執行完畢進行出棧。
  • 回收方式
    有一個記錄當前執行狀態的指針(稱爲 ESP)指向活動棧,函數執行完畢,esp下移到後一節點,銷燬當前函數執行上下文。新的函數執行上下文入棧直接覆蓋掉銷燬的空間即可 .
function test() {
  const a = { name: 'a' };
  function showName() {
    const b = { name: 'b' };
  }
  showName();
}
test();

在這裏插入圖片描述

  • 定義
    對象的值等大數據保存在堆中。

  • 回收方式
    使用 JavaScript 中的垃圾回收器進行回收,通過標記的方式進行回收。
    採用 可訪問性(reachablility)算法來判斷堆中的對象是否爲活動對象。這個算法其實就將一些GC Root 作爲初始存活對象的集合,從 GC Root 對象觸發,遍歷 GC Root中的所有對象

    • 能夠通過 GC Root(全局 wimdow 、dom樹、棧上的變量、回收非活動對象佔據的內存)遍歷到的對象會被認爲是可訪問的,我們將其標記爲活動對象,必須保留
    • 如果一個對象無法通過 GC Root 遍歷到,那麼就認爲這個對象是不可訪問的,可能需要被回收,並標記爲非活動對象

堆的垃圾回收

在垃圾回收領域有一個代際假說的概念,大致意思就是數據分爲生命週期短的和長久的。
根據代際假說,v8對堆的數據保存分爲新生代區域老生代區域兩大塊。這兩區域的垃圾回收是不同的,分別爲副垃圾回收器主垃圾回收器

  • 新生代區域
    存儲空間小,不能存放大對象

  • 老生代區域
    空間大,存活時間長。新生代經過2次GC仍存活的的變量

  • 副垃圾回收器
    通過將新生代區域平分爲2塊區域:對象區空閒區。當活動區中內存滿時啓動垃圾回收,遍歷對象進行垃圾標記,將活動的對象複製到空閒區,移動到空閒區的對象是按順序來的,因此不用去整理。處理完後,將對象區空閒區翻轉,完成垃圾回收。複製操作需要時間成本,因此爲了效率,空間一般設置的很小。空間小,容易填滿,因此又採用了對象晉升策略,經過兩次垃圾回收依然存活的對象就會被移動到老生區

  • 主垃圾回收器
    採用標記-清除(Mark-Sweep)的算法進行垃圾回收。解決標記-清除空間不連續引入標記-整理(Mask-Compact),標記完後,先將所有存活的對象向一端移動,然後直接清理掉這一端以外的內存。

優化效率

  • 併發標記: 在主程序運行階段,併發的對變量進行標記處理,防止中斷js主線程。筆辯主線程、輔助線程同時修改同一對象,需實現讀寫鎖等功能。

  • 並行整理:進行整理時佔用主線程,在此基礎上,啓動多個輔助線程一起處理,加快速度。

  • 增量整理:由於在整理時是佔用的主線程,會阻塞js運行,因此通過增量的方式,將一次處理分成多個小任務處理,減小對用戶的影響。js運行與標記相互交叉,防止變量引用在a,b之間變換,造成標記失敗,使用黑白灰三色標記法進行處理。

  • 黑白灰三色標記

    • 黑:節點以及子節點已處理完
    • 灰:正在處理的節點。黑節點的子節點不能爲白節點,直接置灰(寫屏障)
    • 白: 非活動對象,等待回收
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章