node 垃圾回收機(jī)制
變量,對象都在堆中.(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)存.