深刻淺出node.js學習筆記—node內存管理及GC機制

在node.js中,內存主要分爲兩個部分,堆內存和棧內存javascript

  • 堆內存(heap):存放對象和閉包上下文,v8使用垃圾回收機制管理堆內存
  • 棧內存(stack):存放局部變量,棧內存的分配比較簡單,當程序離開某做用域後,其棧指針下移(回退),整個做用域的局部變量都會出棧被回收。

可經過process.memoryUsage()查看內存使用狀況,單位爲字節
圖片描述java

  • rss是分配的總體物理內存,包括堆、棧、代碼段
  • heapTotal是總體堆內存
  • heapUsed是被使用的堆內存
  • external: 表明v8管理的綁定到javascript的c++對象的內存

一般狀況下,v8對堆內存的分配爲,64位系統下1.4GB,32位系統下0.7GBnode

node將堆內存分爲新生代和老生代c++

  • 新生代:存放存活時間較短的對象
  • 老生代:存放存活時間較長的對象

在分代的基礎上,對於新生代使用Scavenge算法,老生代使用Mark-Sweep和Mark-Compact算法

  • 對象已經經歷過一次複製翻轉操做。
  • To空間使用比例超過25%,設置25%的比例是由於,To空間將變成From空間,若是使用比例太高,可能影響後續的內存分配。

Scavenge算法
Scavenge算法主要經過Cheney算法實現,Cheney算法將新生代分爲兩部分,叫作SemiSpace空間,該兩個SemiSpace空間分別叫作From空間和To空間
From空間爲使用空間,To空間爲閒置空間。分配新的內存空間時會分配到From空間。開始進行垃圾回收時,會檢查From空間內的對象,將存活對象複製至To空間,釋放From空間,而後將From空間和To空間進行翻轉。
Scavenge算法的優勢是速度快,無內存碎片,缺點是,只能使用通常的內存空間,可是因爲新生代都是存活時間較短的對象,須要複製的對象屬於少數。屬於使用空間換時間的典型算法。只適用於新生代垃圾回收策略。閉包

在新生代回收階段,若是存活對象知足如下兩個條件,會將該對象移動至老生代,該階段叫作晉升spa

  • 對象已經經歷過一次複製翻轉操做。
  • To空間使用比例超過25%,設置25%的比例是由於,To空間將變成From空間,若是使用比例太高,可能影響後續的內存分配。

Mark-Sweep(標記清除)和Mark-Compact(標記整理)
Mark-Sweep分爲標記和清除兩個階段,在標記階段遍歷全部老生代對象,對還存活的對象進行標記,在清除階段釋放未被標記的內存。
圖片描述
Mark-Sweep最大問題是,通過清除階段後,內存空間會出現不連續狀態,影響之後的內存分配。可能出現一個對象,須要分配內存空間很大,而現有內存碎片不能完成分配,進行提早垃圾回收,該回收是沒有必要的。
爲了解決Mark-Sweep的內存碎片問題,Mark-Compact被提了出來,它主要是在標記以後,將存活的對象往一側移動,完成移動後,直接釋放邊界外的內存。
圖片描述指針

Incremental Marking
該三種算法執行時,爲了保證javascript應用邏輯與垃圾回收機制保持一致,垃圾回收時都須要將應用邏輯中止,這種狀況稱之爲「全停頓
新生代Scavange算法,因爲分配內存空間較小,存活對象較少,全停頓影響較少。
可是老生代內存空間較大,存儲對象較多,全停頓時間較長。因此V8爲了減小停頓空間,從標記階段開始,改成增量標記(Incremental Marking)。將總體拆分爲小「步進」,沒執行一個「步進」就讓js應用邏輯執行一下子, 垃圾回收與應用邏輯交替進行。對象

相關文章
相關標籤/搜索