Node 垃圾回收機(jī)制

node 垃圾回收機(jī)制

http://algo.site/?cat=53

變量,對象都在堆中.(Buffer有C++來接管分配)

V8的垃圾回收機(jī)制主要基于分代式垃圾回收機(jī)制.

在V8中,主要將內(nèi)存分為新生代和老生代兩代.新生代中的對象為存活時(shí)間較短的對象,老生代中的對象
為存活時(shí)間較長或常駐內(nèi)存的對象.

```
---------------------------------------------
|        |                                   |
| 新生代的 |      老生代的內(nèi)存空間                |
| 內(nèi)存空間 |                                   |
|        |                                   |
---------------------------------------------
```

V8堆的整體大小就是新生代所有內(nèi)存空間+老生代的內(nèi)存空間.

在默認(rèn)情況下,如果一直分配內(nèi)存,在64位系統(tǒng)和32位系統(tǒng)下會(huì)分別只能使用約1.4G(1464MB)和約0.7G(732MB)的大小.

不過可以在node啟動(dòng)的時(shí)候更改

  • --max-old-space-size 命令行參數(shù)可以用于設(shè)置老生代內(nèi)存空間
  • --max-new-space-size 命令參數(shù)數(shù)可以用于設(shè)置新生代內(nèi)存空間


Scavenge 算法

在分代的基礎(chǔ)上,新生代中的對象主要通過Scavenge算法進(jìn)行垃圾回收.在Scavenge算法的具體實(shí)現(xiàn)中,主要采用Cheney算法.

Cheney算法是一種采用復(fù)制方式實(shí)現(xiàn)的垃圾回收.它將堆內(nèi)存一分為二,每一部分空間稱為semispace.
在這兩個(gè)semispace空間中,只有一個(gè)處于使用中,另一個(gè)處于閑置狀態(tài).處于使用狀態(tài)的semispace空間稱為From空間,
處于閑置狀態(tài)的空間稱為To空間.當(dāng)我們分配對象時(shí),先在From空間中進(jìn)行分配.當(dāng)開始進(jìn)行垃圾回收時(shí),會(huì)檢查From空間中的存活
對象,這些存活對象被復(fù)制到To空間,而非存活空間對象占用的空間將被釋放.完成復(fù)制后,From空間和To空間的角色發(fā)生互換.

簡而言之,在垃圾回收的過程中,就是通過將存活對象在兩個(gè)semispace空間之間進(jìn)行復(fù)制.

由于Scavenge算法是典型的犧牲空間換取時(shí)間的算法,所以無法大規(guī)模的應(yīng)用到所有垃圾回收中.
但是Scavenge算法非常適合在新生代中,因?yàn)樾律袑ο蟮纳芷谳^短,恰恰適合這個(gè)算法.

```
---------------------------------------------------------------
|        |        |                                           |
| semi   | semi   |                                           |
| space  | space  |          老生代空間                         |
| (From) | (From) |                                           |
|        |        |                                           |
---------------------------------------------------------------
```

對象晉升的條件主要有兩個(gè),一個(gè)是對象是否經(jīng)歷過Scavenge回收,一個(gè)是To空間的內(nèi)存占用比超過限制.

在默認(rèn)情況下,V8的對象分配主要集中在From空間中.對象從From空間中復(fù)制到To空間時(shí),會(huì)檢查它
的內(nèi)存地址來判斷這個(gè)對象是否已經(jīng)經(jīng)歷過一次Scavenge回收.如果經(jīng)歷過了,會(huì)將該對象從From空間復(fù)制
到老生代空間中.如果沒有,則復(fù)制到To空間中.

另一個(gè)判斷條件是To空間的內(nèi)存占比.當(dāng)要從From空間復(fù)制一個(gè)對象到To空間時(shí),如果To空間已經(jīng)使用超過了25%,
則這個(gè)對象直接晉升到老生代中.

設(shè)置25%這個(gè)限制值的原因是當(dāng)次Scavenge回收完成后,這個(gè)To空間將變成From空間,
接下來的內(nèi)存分配將在這個(gè)空間進(jìn)行.如果占比過高會(huì)影響后來的內(nèi)存分配.

對象晉升后,將會(huì)在老生代空間作為存活周期較長的對象對待,接受新的回收算法處理.

Mark-Sweep & Mark-Compact

V8在老生代中主要采用Mark-Sweep和Mark-Compact相結(jié)合的方式進(jìn)行垃圾回收.

Mark-Sweep是標(biāo)記清除的意思,它分為標(biāo)記和清除兩個(gè)階段.與Scavenge相比,Mark-Sweep并不將內(nèi)存空間
劃分為兩半,所以不存在浪費(fèi)一半空間的行為.與Scavenge復(fù)制活得對象不同,Mark-Sweep在標(biāo)記階段遍歷堆中所有對象.
并標(biāo)記活著的對象,在隨后的清除階段中,之清除沒有被標(biāo)記的對象.
可以看出,Scavenge中之復(fù)制活著的對象,而Mark-Sweep只清理死亡對象.
活對象在新生代中只占較小部分,死對象在老生代中只占較小部分,這是兩種回收方式能高效處理的原因.

但是Mark-Sweep最大問題是進(jìn)行一次標(biāo)記清除回收后,內(nèi)存空間會(huì)出現(xiàn)不連續(xù)的狀態(tài).這種內(nèi)存碎片會(huì)對后續(xù)的內(nèi)存分配造成問題.
Mark-Compact是標(biāo)記整理的意思,是在Mark-Sweep基礎(chǔ)上演變而來.它們的差別在于對象標(biāo)記死亡后,在整理的過程中,將活著
的對象往一端移動(dòng),移動(dòng)完成后,直接清理掉邊界外的內(nèi)存.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文引用自這里這篇文章的所有內(nèi)容均來自 樸靈的《深入淺出Node.js》及A tour of V8:Garbage...
    楠小忎閱讀 1,685評(píng)論 0 2
  • JVM內(nèi)存區(qū)域 JVM將其管理的內(nèi)存分為若干數(shù)據(jù)區(qū)域,這些數(shù)據(jù)區(qū)域分布情況如下圖所示: 程序計(jì)數(shù)器:一塊較小內(nèi)存區(qū)...
    luoxn28閱讀 777評(píng)論 0 0
  • 垃圾收集基礎(chǔ) Java 語言的一大特點(diǎn)就是可以進(jìn)行自動(dòng)垃圾回收處理,而無需開發(fā)人員過于關(guān)注系統(tǒng)資源,例如內(nèi)存資源的...
    Austin_Brant閱讀 821評(píng)論 0 2
  • 1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虛擬機(jī)(JVM)垃圾回收器提供...
    簡欲明心閱讀 90,375評(píng)論 17 311
  • 左耳聽見悲傷 右耳訴說心疼 我不喜歡說話 每天都要說很多話 敷衍的 違心的 官方的 客套話 我不喜歡笑 每天卻要不...
    一直的思念閱讀 222評(píng)論 0 0

友情鏈接更多精彩內(nèi)容