javascript垃圾回收機制 - 標記清除法/引用計數/V8機制

Js GC原理:

找出那些再也不繼續使用的變量,而後釋放其所佔用的內存,垃圾回收器會按照固定的時間間隔週期性地執行這一操做瀏覽器

Js GC 策略:

  • 標記清除法
  • 引用計數

JavaScript 內存分配:

  • 定義變量時就完成了內存分配,還能夠經過函數調用分配內存,使用值的過程其實是對分配內存進行讀取與寫入的操做

標記清除法:

  • 標記方式:特殊位的反轉、維護一個列表
  • 原理:垃圾收集器在運行的時候會給存儲在內存中的全部變量都加上標記,而後它會去掉環境中的變量已經被環境中變量被標記爲引用的變量,在此以後再被標記的變量將被視爲準備刪除的變量。最後垃圾回收器清除標記的變量,回收它們所佔用的內存空間
  • 目前主流瀏覽器都是使用標記清除式的垃圾回收策略,只不過收集的間隔有所不一樣

引用計數:

  • 原理:每次引用加一,被釋放時減一,當這個值的引用次數變成 0 時,就能夠將其內存空間回收
  • 缺點:循環引用(obj1 和 obj2 經過各自的屬性相互引用,也就是說,這兩個對象的引用次數都是 2)

IE兼容問題

  • 在 IE9 以前,IE 中有一部分對象並非原生 JavaScript 對象。例如,BOM 和 DOM 中的對象就是 C++ 實現的 COM 對象,而 COM 對象的垃圾收集機制採用的是引用計數策略。所以,即便 IE 中的 JavaScript 引擎使用標記清除策略實現,可是 JS 訪問的 COM 對象依然是基於引用計數策略的。能夠在 IE 中涉及到 COM 對象,就會存在循環引用的問題
  • 解決:將變量設置爲 null

V8內存機制

    • V8 引擎會限制 JavaScript 所能使用的內存大小
    • 性能問題:(運行時間間隔)函數

      • IE7 以前的垃圾收集器是根據內存分配量運行的,達到某一個臨界值就是啓動垃圾回收器性能

        • 缺點:若是該腳本在其生命週期須要一直保持這麼多變量,垃圾回收器就不得不頻繁運行。
      • 瀏覽器可自動觸發: window.CollectGarbage()
      • 避免:執行代碼中只保留必要的數據,一旦數據再也不有用,經過設置爲 null 來釋放其引用(適用於大多數全局變量和全局對象的屬性)
    • V8 的堆構成指針

      • 新生區:大多數對象被分配在這裏。新生區是一個很小的區域,垃圾回收在這個區域很是頻繁,與其餘區域相獨立。
      • 老生指針區:這裏包含大多數可能存在指向其餘對象的指針的對象。大多數在新生區存活一段時間以後的對象都會被挪到這裏。
      • 大對象區:這裏存放體積超越其餘區大小的對象。每一個對象有本身 map 產生的內存。垃圾回收器從不移動大對象。
        -代碼區:代碼對象,也就是包含 JIT 以後指令的對象,會被分配到這裏。這是惟一擁有執行權限的內存區(不過若是代碼對象因過大而放在大對象區,則該大對象所對應的內存也是可執行的。譯註:可是大對象內存區自己不是可執行的內存區)。
        -Cell 區、屬性 Cell 區、Map 區:這些區域存放 Cell、屬性 Cell 和 Map,每一個區域由於都是存放相同大小的元素,所以內存結構很簡單
    • 分代回收code

      • 緣由:絕大多數對象的生存期很短,只有某些對象的生存期較長
      • 過程:

        一、對象起初會被分配在新生區(一般很小,只有 1-8 MB)在新生區的內存分配很是容易:咱們只需保有一個指向內存區的指針,不斷根據新對象的大小對其進行遞增便可。當該指針達到了新生區的末尾,就會有一次清理(小週期),清理掉新生區中不活躍的死對象。對象

        二、活躍超過 2 個小週期的對象,則需將其移動至老生區老生區在標記-清除或標記-緊縮(大週期)的過程當中進行回收。大週期進行的並不頻繁。一次大週期一般是在移動足夠多的對象至老生區後纔會發生。至於足夠多究竟是多少,則根據老生區自身的大小和程序的動向來定。生命週期

    相關文章
    相關標籤/搜索