大前端— js 內存

1.可達的內存

v8 本身有內存回收機制,並且會回收 所有不可達的內存,那麼什麼是 可達的內存呢?

從全局執行上下文出發,能找到的,就被認爲是可達的

如下所示, obj 就是 可達的,而 obj1 obj2 就是不可達的

var obj = {parent: obj}

function fn() {
  const obj1 = {}
  const obj2 = {}
  obj1.name = obj2
  obj2.name = obj1
}

而如下所示,user 就是可達的,name 屬性是不可達的

const user = {age: 1}
const list = [user.age] // 引用 + 1

function fn() {
  const name = 'jack'
}
fn()

2. v8 中的內存機制

  64位 1.5G 32位 800M

  新生代 老生代
內存大小(64位) 32M 14G
內存大小(32位) 16M 700M
執行的操作 複製、標記整理 標記清除、標記整理、增量標記
  1. 其中新生代 還分爲 兩個區域,一個是from,一個是to,專門用來執行 複製 操作
  2. 所謂的複製 操作 指的是 在 from 區域 中的內存要 用完之前,就會把 當前 可達的內存 複製一份,到 to 區域中去,這其中還 可以順便整理內存空間,使得獲得一個 比較大的連續的內存空間
  3. 然後 在一輪的 GC 之中還存活着的話,那就把 新生代的 內存放到 老生代去
  4. 在這之後,to 空間 就變成了 from 空間,而原來的 from 空間就會被清空,成爲 to 空間,也就是進行 調換

下面重點來簡單介紹一下 各種內存 處理的算法

  執行過程 是否可以立即執行 缺點 優點
引用計數   引用 計數器,判斷當前的引用數是否爲0,當爲0的話,就可以直接刪除 是,只要計數器爲 0,可以立即執行

1、無法回收循環引用的對象

2、  空間開銷大

 
標記清除

  1、遍歷所有對象找標記活動對象

        其實就是從代碼層面 去 找一遍能找到的對象, global 開始查找

      找到了就進行標記

  2、遍歷 所有對象清除沒有標記對象

      然後 把所有沒有被標記的 給 刪除

1、容易導致 空間的碎片化,空間的不連續

 2、不能立即回收對象,回收的時候,程序停止工作

解決了 循環引用的問題
標記整理

當想把 新生代 往老生代的空間移動,但是不足以 完成晉升,就會對老生代執行

和 標記清除一樣,但是會對空間進行整理,讓空間能夠出現連續

不能立即回收對象,回收的時候,程序停止工作,最長也就1s 這裏的執行比較緩慢,畢竟是對 老生代這麼大的東西進行整理,所以會導致 js 的性能問題
標記增量

1、對需要進行清除的 內存進行 一點一點地進行標記,但是並不立刻刪除

2、然後 標記一點,就執行一段 js 代碼,接着再 標記一點,又去執行一點代碼(類比於 js 中的 requestIdeCallback)

3、等到標記完成了,對所有標記的 垃圾對象進行一次性刪除

執行的時候會導致 js 停止執行 並不會導致 js 一次性停止太長的時間,提高用戶體驗
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章