- 程序的運(yùn)行需要內(nèi)存焚廊。
- javaScript使用自動內(nèi)存管理纵诞,這被稱為“垃圾回收機(jī)制”绘闷。
- 優(yōu)點(diǎn)是可以簡化開發(fā)忆肾、節(jié)省代碼
- 缺點(diǎn)是無法完整的掌握內(nèi)存的分配與回收的具體過程
NodeJS中的內(nèi)存管理
- 網(wǎng)頁端的內(nèi)存泄露
- 對于持續(xù)運(yùn)行的服務(wù)進(jìn)程N(yùn)ode服務(wù)器端程序室梅,必須及時釋放不再用到的內(nèi)存戏仓。否則內(nèi)存占用越來越高, 輕則影響系統(tǒng)性能亡鼠,重則導(dǎo)致進(jìn)程崩潰赏殃。
- 如果不再用到的內(nèi)存沒有及時釋放,就叫做內(nèi)存泄露间涵。
V8內(nèi)存管理
1. v8內(nèi)存限制
- 在62位操作系統(tǒng)可以使用1.4G內(nèi)存
- 在32位操作系統(tǒng)中可以使用0.7G內(nèi)存
2. V8內(nèi)存管理
Js對象都是通過V8進(jìn)行分配管理內(nèi)存的
-
process.memoryUsage
返回一個對象仁热,包含了Node進(jìn)程的內(nèi)存占用信息。
rss(resident set size)
:所有內(nèi)存占用勾哩, 包括指令區(qū)和堆棧抗蠢。heapTotal
: “堆”占用的內(nèi)存,包括用到的和沒用到的思劳。heapUsed
:用到的堆的部分迅矛,判斷內(nèi)存泄露,以heapUsed
字段為準(zhǔn)潜叛。external
: V8引擎內(nèi)部的C++對象占用的內(nèi)存
3.為何限制內(nèi)存大小
- 因?yàn)閂8的垃圾收集工作原理導(dǎo)致的秽褒,1.4G內(nèi)存完成一次垃圾收集需要1S以上
- 這個暫停時間成為
stop the world
, 在這個期間壶硅,應(yīng)用的性能和響應(yīng)能力都會下降。
4. 如何打開內(nèi)存內(nèi)存限制
- 一旦初始化成功销斟, 生效后不能再修改
- -max-new-space-size, 最大new space大小庐椒,執(zhí)行scavenge回收,默認(rèn)16M,單位KB
- -max-old-space-size, 最大old space大小蚂踊,執(zhí)行MarkSweep回收约谈,默認(rèn)1M,單位MB
node --max-old-space-size=2000 單位是M
V8垃圾回收機(jī)制
- V8是基于分代的垃圾回收。
- 不同代的垃圾回收機(jī)制也不一樣
- 按存活時間分為新生代和老生代
1. 分代
年齡小的是新生代,由From區(qū)域和To區(qū)域兩個區(qū)域組成:
在64位系統(tǒng)里悴势,新生代內(nèi)存是32M,From區(qū)域和To區(qū)域各占用16M
在32位系統(tǒng)里窗宇,新生代內(nèi)存是16M,From區(qū)域和To區(qū)域各占用8M年齡大的是老生代,默認(rèn)情況下,
64為系統(tǒng)下老生代內(nèi)存是1400M
32為系統(tǒng)下老生代內(nèi)存是700M
分代示意圖
2. 引用計(jì)數(shù)
- 語言引擎有一張引用表特纤,保存了內(nèi)存里面所有的資源的引用次數(shù)军俊。
- 如果一個值的引用次數(shù)是0,就表示這個值不再用到了捧存,因此可以將這塊內(nèi)存釋放粪躬。
3,新生代垃圾回收
- 新生代區(qū)域一分為二,每個16M昔穴,一個使用镰官,一個空閑
- 開始垃圾回收的時候,會檢查FROM區(qū)域中的存活對象吗货,如果還活著泳唠,拷貝到TO空間,完成后釋 放空間
- 完成后 FROM 和 TO 互換
- 新生代掃描的時候是一種廣度優(yōu)先的掃描策略
- 新生代的空間小宙搬,存活對象少
-
當(dāng)一個對象經(jīng)歷過多次的垃圾回收依然存活的時候笨腥,生存周期比較長的對象會被移動到老生代, 這個移動過程被成為晉升或者升級:
經(jīng)過5次以上的回收還存在
TO的空間使用占比超過25%勇垛,或者超大對象
4.老生代
- mark-sweep(標(biāo)記清除) mark-compact(標(biāo)記整理)
- 老生代空間大脖母,大部分都是活著的對象,GC耗時比較長
- 在GC期間無法響應(yīng),STOP-THE-WORLD
- V8有一個優(yōu)化方案闲孤,增量處理谆级,把一個大暫停換成多個小暫停 INCREMENT-GC
mark-sweep(標(biāo)記清除)
- 標(biāo)記活著的對象,隨后清除在標(biāo)記階段沒有標(biāo)記的對象讼积,只清理死亡對象
- 問題在于清除后會出現(xiàn)內(nèi)存不連續(xù)的情況肥照,這種內(nèi)存碎片會對后續(xù)的內(nèi)存分配產(chǎn)生影響
- 如果要分配一個大對象,碎片空間無法分配
mark-compact(標(biāo)記整理)
- 標(biāo)記死亡后會對對象進(jìn)行整理勤众,活著的對象向左移動建峭,移動完成后直接清理掉邊界外的內(nèi)存
incremental marking 增量標(biāo)記
- 以上三種回收時都需要暫停程序執(zhí)行,收集完成后才能恢復(fù)决摧,
STOP-THE-WORLD
在新生代影響 不大亿蒸,但是老生代影響就非常大了 - 增量標(biāo)記就是把標(biāo)記改為了增量標(biāo)記凑兰,把一口氣的停頓拆分成了多個小步驟,做完一步程序運(yùn)行 一會兒边锁,垃圾回收和應(yīng)用程序運(yùn)行交替進(jìn)行姑食,停頓時間可以減少到1/6左右 包括垃圾回收的占用時間
3種垃圾回收算法對比