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