node記憶體溢位問題

2020-08-09 01:02:31

一 、現象描述

由於專案在執行或者專案打包時突然停止build專案或者崩潰掉,工作臺會頻繁報出記憶體溢位報出:FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

在这里插入图片描述

二、爲什麼Nodejs記憶體會溢位?

要明白node記憶體溢位的原因,先瞭解一下node記憶體機制 機製。下面 下麪簡單介紹node機制 機製和原理(介紹node原理較淺淺,詳細內容請看:Nodejs官網

1、V8的記憶體機制 機製

  • 記憶體的分配

一切JavaScript物件都用堆來儲存!!!

  1. 當我們在程式碼中宣告變數並賦值時,使用物件的記憶體就分配在堆中。
  2. 如果已申請的對空閒記憶體不夠分配新的物件,將會繼續申請堆記憶體,直到堆的大小超過V8記憶體的限製爲止。
  3. 這也是注意到爲什麼要一直少用全域性作用域,也是爲了高效使用記憶體,並且和垃圾回收機制 機製緊密聯繫,詳細可以看一下大佬講解==》Node高效使用記憶體在这里插入图片描述
  • 記憶體的限制

Node記憶體其實並不是和後端語言一樣,對記憶體使用沒有多少限制,只是在Node使用記憶體中,只能使用系統實體記憶體的一部分,64位元系統下約爲1.4GB,32位元系統下約爲0.7GB,這也是歸結於Node使用了執行在瀏覽器的V8引擎。

  • 爲什麼記憶體限制

記憶體限制主要原因是v8的垃圾回收制度。1.5GB記憶體做一次小的回收需要50MS,做一次非增量性回收需要1S以上,並且這會使JS執行緒暫停。因此限制記憶體。

  • 不受記憶體限制的特例

在介紹不受記憶體限制前需要瞭解一下node記憶體分爲兩類:

  1. V8記憶體: JavaScript內建物件(String、Array、Date、Boolean、Number、Math等物件),執行時使用V8記憶體
  2. 系統記憶體: Buffer是一個Node.js的擴充套件物件,使用底層的系統記憶體,不佔用V8記憶體空間。與之相關的檔案系統fs和流Stream流操作,都不會佔用V8記憶體。
  • 修改記憶體限制大小
  // 單位爲KB 新生代
 node --max-nex-space-size=1024 index.js
 // 單位爲MB 老生代
 node --max-old-space-size=1700 index.js 
`

2. V8的垃圾回收機制 機製簡說

1、V8的垃圾回收策略主要基於 「分代式垃圾回收機制 機製」,基於這個機制 機製,V8把記憶體分爲 「新生代(New Space)」「老生代 (Old Space)」

所以知道爲什麼新生代中的物件爲存活時間較短的物件分配的容量少,老生代中的物件爲存活時間較長或常駐記憶體的物件而分配的容量多。

  • 爲什麼要分成新老兩代?

垃圾回收演算法有很多種,但是並沒有一種是勝任所有的場景,在實際的應用中,需要根據物件的生存週期長短不一,而使用不同的演算法,已達到最好的效果。在V8中,按物件的存活時間將記憶體的垃圾回收進行不同的分代,然後分別對不同的記憶體施以更高效的演算法。

三、node溢位解決方案

說了那麼多,也大概明白node記憶體溢位前因後果啦,針對node溢位解決方案很多,下面 下麪簡單說我的解決方案:

  • 在package.json的scripts中加上設定:
    在这里插入图片描述

node指令可以檢視記憶體就可知道自己是否申請到擴容,

D:\vanke\gjwy-front>node
> process.memoryUsage()  // 檢視node記憶體的指令
{ rss: 24428544, //   進程的常駐記憶體
  heapTotal: 7684096,    // 已申請到的堆記憶體
  heapUsed: 5096712,  // 當前使用的堆記憶體
  external: 9039 }

在这里插入图片描述

  • 新增依賴包
npm install --save-dev increase-memory-limit
執行npm run fix-memory-limit(只需執行一次即可)
重新啓動專案即可

四、總結

1、加強node深入研究,在瞭解過程也對間接地學習相關聯知識,但還需要花很多時間去考究和學習。
2、 簡單瞭解V8引擎的前生今世的的由來, 詳細請點選 V8引擎