v8是Google推出的JS引擎,他不僅提升了Chrome的性能,也為node提供了很好的支持,本篇博文幫助大家大致了解一下v8其中的垃圾回收機制。
一、內存限制
v8限制用戶只能使用部分內存(當然,這個限制大小也可以用戶自己設置,默認64位約為1.4GB,32位約為0.7GB)
原因:以1.5GB的垃圾回收堆內存為例,v8做一次小的垃圾回收需要50ms以上,做一次非增量式的垃圾回收甚至要1秒以上。
在這樣子時間開銷下,性能和響應能力直線下降。
二、分代式垃圾回收機制
出現原因:在自動垃圾回收的演變過程中,沒有固定一種回收算法能勝任所有場景,采取分代式,可以對不同的代進行不能的處理,以提高效率。
堆上: ![]()
新生代空間:存放存活時間短的對象
老生代空間:存放存活時間長的對象
1、新生代算法: 主要采用Scavenge算法

過程:
先在新生代區,將堆內存對半分,一半處於使用(即From區),另一半處於閑置(即To區),平時在From區進行操作。到了要回收的時候,檢測From區的對象,存活的對象復制到To
區,然后From區被釋放了,之后對To區和From區調換名字,繼續重復之前操作
缺點:只能使用一半空間,耗空間
優點:只需要復制少部分存活的對象,因為生命周期短的對象中存活的比較少,節省時間
注意:當一個對象被復制多次依然存活,則被晉升到老生代,進行管理
(晉升條件:經歷過Scavenge算法或To區使用超出25%)
2、老生代算法: 標記清除算法 搭配 標記整理算法
過程:
標記清除算法,先將存活的對象進行標記,清除時只清除沒有標記的(老生代中都是生命周期長的對象,剛好死亡的對象少),不過此時會出現內存不連續的情況。但是,如果此時需要放一個大對象,則放不下,從而導致再次引起回收。然而這次回收是不必要的。

標記整理算法,先將死亡的對象進行標記,然后將存活得對象往一段移動,移動完成后,清理掉邊界外的內存。
總結:

可以看出標記整理相對較慢,V8主要還是使用標記清除,只有在新生代發生晉升,導致老生代分配不出足夠空間時,采用標記整理
3、增量標記
上述三種方式局限:都需要將應用暫停下來,等待執行回收,回收執行完畢才繼續應用邏輯。特別是v8老生代,因為配置較大,存活的對象多,導致標記、清除、整理帶來的停頓更加嚴重。
增量標記可以將上述步驟拆成更細的“粒度”,讓回收中的標記階段和應用邏輯交替進行,v8引入這個方式后最大停頓減少到原本1/6

4、延遲清除、增量式整理
將清除階段和整理階段也進行了“增量式改造”
備注:摘取《深入淺出nodejs》
