天天看點

Nodejs記憶體控制詳解(上篇)

Nodejs記憶體控制詳解(上篇)

1 V8的垃圾回收機制與記憶體限制

JavaScript與Java一樣,由垃圾回收機制來進行自動的記憶體管理。對于性能敏感的伺服器端程式,記憶體管理的好壞、垃圾回收狀況是否優良,都會對服務構成影響。而在Node中,這一切與V8引擎息息相關。

1.2 V8的記憶體限制

Node中通過JavaScript隻能使用部分記憶體(64位約1.4G,32位約0.7G)。V8對記憶體做了限制。是以這種限制下,将會導緻Node無法直接操作大記憶體對象。

1.3 V8的對象配置設定

V8中,所有的JavaScript對象都是通過堆來配置設定的。

可以使用以下指令檢視Node中V8記憶體的使用量。

> $ node
> process.memoryUsage();
{ rss: 25939968,
  heapTotal: 5767168,//已申請到的堆記憶體
  heapUsed: 4707312,//目前使用的量
  external: 8671 }           

至于rss為何物,我們會在下面介紹。

V8的堆示意圖:

限制記憶體原因:

  • 首先V8是為浏覽器而設計的;前期足以滿足網頁端的需求;
  • 深層原因是V8的垃圾回收機制,垃圾回收耗時,引起JavaScript線程暫停執行時間。
  • 可以手工調整記憶體大小
node --max-old-space-size=1700 test.js  //機關為MB。設定老生代

node --max-new-space-size=1024 test.js //機關為KB。設定新生代
           

1.4 V8的垃圾回收機制

主要的垃圾回收政策是

基于分代式

的垃圾回收機制:

将對象的存活時間進行不同的分代

V8中,主要将記憶體分為新生代和老生代。新生代中的對象為存活時間較短的對象,老生代中的對象為存活時間較長或常駐記憶體的對象。

  • 前面講到的指令是可以分别設定新生代和老生代的大小。
  • 新生代和老生代的最大值需要在啟動時就指定,是以無法動态 擴充。手工設定新生代或老生代的記憶體,隻能在啟動時就指定,無法動态的擴充。

Scavenge算法

在分代的基礎上,新生代中的對象主要通過Scavenge算法進行垃圾回收。Scavenge算法的具體實作中采用了Cheney算法。

  • Cheney算法主要使用了

    複制

    的方式實作。
  • 新生代堆記憶體被一分為二
  • From區存放處于使用狀态對象
  • TO區為閑置空間
  • 配置設定對象時首先在From配置設定
  • 垃圾回收時,檢查From空間中的存活對象,将這些對象複制到TO空間。非存活對象直接釋放對應空間。
  • 垃圾回收實際上就是将對象在

    FROM

    TO

    兩個空間之間複制。
  • 多次複制仍然存活的對象,即生命周期較長的對象,會被移動到老生代。
  • 對象從新生代到老生代的過程稱為

    晉升

  • 對象晉升過程:

另一個判斷條件是:TO空間使用是否超過25%。如果超過,直接移動到老生代。

設定25%這個值,是因為當Scavenge完成回收後,這個TO區将變成From區,後面的對象配置設定要在這個區中進行。如果占比過高,會影響後續的記憶體配置設定。

Scavenge的缺點是隻能使用堆記憶體的一半。是以無法大規模的運用到所有的垃圾回收中。但是時間效率上有優異的表現。是以非常适合新生代的垃圾回收,因為新生代中的對象存活周期都較短。

Mark-Sweep & Mark-Compact算法

老生代中主要采用這兩種算法進行垃圾回收。

因為老生代中的存活對象占比較大,是以使用Scavenge算法會有弊端:

  • 存活對象多,複制效率低;
  • 浪費一半空間;

1.Mark-Sweep:标記清除

分為标記、清除兩個階段;
  • 标記階段會周遊堆中的所有對象,并隻标記活着的對象;
  • 清除階段隻清除沒有被标記的對象;

Mark-Sweep | Scavenge

--- | ---

隻清理死亡對象 | 隻複制存活對象

死對象在老生代中比重小 | 活對象在新生代中比重小

Mark-Sweep的最大問題即是:在清理完後,記憶體會出現不連續的狀态。導緻後續對記憶體的配置設定可能出現問題,如無法配置設定一個大對象。

2.Mark-Compact:标記整理

為了解決Mark-Sweep的問題。Mark-Compact在标記對象死亡後,在整理過程中,将活着的對象往一端移動,移動完成後,直接清理掉邊界外的記憶體。

算法比較

| 算法 | Mark-Sweep | Mark-Compact | Scavenge

---| --- | -- |--

速度 | 中等| 最慢 | 最快

空間開銷 | 少(有碎片)|少(無碎片)| 雙倍空間(無碎片)

是否移動對象 | 否 | 是 | 是

V8主要使用Mark-Compact,在空間不足以對從新生代中晉升過來的對象進行配置設定時才使用Mark-Sweep。

原文釋出時間為:2018年01月20日

原文作者:

sunangie

本文來源:

開源中國

如需轉載請聯系原作者