Node 是如何做 GC (垃圾回收)的?下面本篇文章就來帶大家了解一下。
node.js極速入門課程:進(jìn)入學(xué)習(xí)
GC,Garbage Collection,垃圾回收。在編程中,一般指的是內(nèi)存自動回收機(jī)制,會定時(shí)將不需要用到的數(shù)據(jù)進(jìn)行清除。
Node.js 底層使用了 V8 引擎。V8 是 Google 開源的一款高性能 JavaScript 引擎,使用了 C++ 進(jìn)行編寫?!鞠嚓P(guān)教程推薦:nodejs視頻教程】
Node.js 的內(nèi)存主要分成三部分:
-
代碼空間:存放代碼段的地方;
-
棧:函數(shù)調(diào)用棧產(chǎn)生的臨時(shí)變量,為一些基本類型,比如數(shù)字、字符串、布爾值,以及對象引用(保存的是地址,不保存對象本身)。
-
堆:存放對象等數(shù)據(jù);
堆內(nèi)存
Node.js 底層使用的是 V8,下面講解一下 V8 的內(nèi)存回收機(jī)制。
首先 JS 中所有的對象都會保存在堆內(nèi)存中。在創(chuàng)建進(jìn)程的時(shí)候,會分配一個(gè)初始大小的堆內(nèi)存,然后我們的對象就會放到里面。
當(dāng)對象越來越多,堆內(nèi)存會不夠用,此時(shí)堆內(nèi)存會動態(tài)地?cái)U(kuò)大。如果到達(dá)一個(gè)最大限制(現(xiàn)在通常是 4GB),就會堆內(nèi)存溢出的錯(cuò)誤,然后終止 Node.js 進(jìn)程。
新生代與老生代
V8 首先將內(nèi)存分成兩部分,或者說兩個(gè)生代(generation):
-
新生代(yong generation):保存一些存活時(shí)間較短的對象;
-
老生代(old generation):保存存活時(shí)間長或者長駐的對象。
新生代很小,這里會存放一些存活時(shí)間很短的對象,通常它們會被頻繁地回收(比如函數(shù)的調(diào)用棧的一些臨時(shí)對象)。
新生代可通過
node --max-semi-space-size=SIZE index.js
修改新生代的大小,單位為 MB。另外,老生代則通過
--max-old-space-size=SIZE
來設(shè)置
新生代的 Scavenge 算法
新生代使用了 Scavenge 算法,是一種基于 copy(復(fù)制)的算法。
新生代會分成兩個(gè)空間,這種空間稱為 semispace,它們?yōu)椋?/p>
-
From 空間:新聲明的對象會放入這里
-
To 空間:用作搬移的空間
新聲明的對象會放入到 From 空間中,F(xiàn)rom 空間的對象緊密排布,通過指針,上一對象緊貼下一個(gè)對象,是內(nèi)存連續(xù)的,不用擔(dān)心內(nèi)存碎片的問題。
所謂內(nèi)存碎片,指的是空間分配不均勻,產(chǎn)生大量小的連續(xù)空間,無法放入一個(gè)大對象。
當(dāng) From 空間快滿了,我們就會遍歷找出活躍對象,將它們 copy 到 To 空間。此時(shí) From 空間其實(shí)就空了,然后我們將 From 和 To 互換身份。
如果一些對象被 copy 了多次,會被認(rèn)為存活時(shí)間較長,將被移動到老生代中。
這種基于 copy 的算法,優(yōu)點(diǎn)是可以很好地處理內(nèi)存碎片的問題,缺點(diǎn)是會浪費(fèi)一些空間作為搬移的空間位置,此外因?yàn)榭截惐容^耗費(fèi)時(shí)間,所以不適合分配太大的內(nèi)存空間,