欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

nodeJs內存泄漏問題詳解

 更新時間:2016年09月05日 08:59:28   作者:jaychen  
由于內存泄漏在Node.js中非常的常見,可能在瀏覽器中應用javascript時,對于其內存泄漏不是特別敏感,但作為服務器語言運行時,你就不得不去考慮這些問題。

之前一次偶然機會發(fā)現(xiàn),react 在server渲染時,當NODE_ENV != production時,會導致內存泄漏。具體issues: https://github.com/facebook/react/issues/7406 。隨著node,react同構等技術地廣泛運用,node端內存泄漏等問題應該引起我們的重視。為什么node容易出現(xiàn)內存泄漏以及出現(xiàn)之后應該如何排查,下面通過一個簡單的介紹以及例子來說明。

首先,node是基于v8引擎基礎上,其內存管理方式與v8一致。下面簡單介紹v8的相關內存特效。

V8內存限制

node基于V8構建,通過V8的方式進行分配跟管理js對象。V8對內存的使用有限制(老生代內存64位系統(tǒng)下約為1.4G,32位系統(tǒng)下約為0.7G,新生代內存64位系統(tǒng)下約為32MB,32系統(tǒng)下約為16MB)。在這樣的限制下,將導致無法操作大內存對象。如果不小心觸碰這個界限,就會造成進程退出。

原因:V8在執(zhí)行垃圾回收時會阻塞JavaScript應用邏輯,直到垃圾回收結束再重新執(zhí)行JavaScript應用邏輯,這種行為被稱為“全停頓”(stop-the-world)。若V8的堆內存為1.5GB,V8做一次小的垃圾回收需要50ms以上,做一次非增量式的垃圾回收甚至要1秒以上。

通過node --max-old-space-size=xxx(單位MB) , node --max-new-space-size=xxx(單位KB) 設置新生代內存以及老生代內存來破解默認的內存限制。

V8的堆構成

V8的堆其實并不只是由老生代和新生代兩部分構成,可以將堆分為幾個不同的區(qū)域:

  1. 新生代內存區(qū):大多數的對象被分配在這里,這個區(qū)域很小但是垃圾回特別頻繁
  2. 老生代指針區(qū):屬于老生代,這里包含了大多數可能存在指向其他對象的指針的對象,大多數從新生代晉升的對象會被移動到這里
  3. 老生代數據區(qū):屬于老生代,這里只保存原始數據對象,這些對象沒有指向其他對象的指針
  4. 大對象區(qū):這里存放體積超越其他區(qū)大小的對象,每個對象有自己的內存,垃圾回收其不會移動大對象
  5. 代碼區(qū):代碼對象,也就是包含JIT之后指令的對象,會被分配在這里。唯一擁有執(zhí)行權限的內存區(qū)
  6. Cell區(qū)、屬性Cell區(qū)、Map區(qū):存放Cell、屬性Cell和Map,每個區(qū)域都是存放相同大小的元素,結構簡單

GC回收類型

增量式GC

表示垃圾回收器在掃描內存空間時是否收集(增加)垃圾并在掃描周期結束時清空垃圾。

非增量式GC

使用非增量式垃圾收集器時,一收集到垃圾即將其清空。

垃圾回收器只會針對新生代內存區(qū)、老生代指針區(qū)以及老生代數據區(qū)進行垃圾回收。對象首先進入占用空間較少的新生代內存。大部分對象會很快失效,非增量GC直接回收這些少量內存。假如有些對象一段時間內不能被回收,則進去老生代內存區(qū)。這個區(qū)域則執(zhí)行不頻繁的增量GC,且耗時較長。

那什么時候才會導致內存泄漏的發(fā)生呢?

內存泄漏的途徑

  1. 內存泄露
  2. 緩存
  3. 隊列消費不及時
  4. 作用域未釋放

Node的內存構成主要是通過V8進行分配的部分和Node自行分配的部分。受V8的垃圾回收限制的主要是V8的堆內存。造成內存泄漏的主要原因:1,緩存;2,隊列消費不及時;3,作用域未釋放

內存泄漏分析

查看V8內存使用情況(單位byte)

process.memoryUsage(); 
  {
    ress: 47038464,  
    heapTotal: 34264656,  
    heapUsed: 2052866  
  }

ress:進程的常駐內存部分

heapTotal,heapUsed:V8堆內存信息

查看系統(tǒng)內存使用情況(單位byte)

os.totalmem()
os.freemem()

返回系統(tǒng)總內存以及閑置內存

查看垃圾回收日志

node --trace_gc -e "var a = []; for( var i = 0; i < 1000000; i++ ) { a.push(new Array(100)); }" >> gc.log  //輸出垃圾回收日志

node --prof //輸出node執(zhí)行時性能日志。 使用windows-tick.processor查看。

分析監(jiān)控工具

v8-profiler 對v8堆內存抓取快照和對cpu進行分析
node-heapdump 對v8堆內存抓取快照
node-mtrace 分析堆棧使用
node-memwatch 監(jiān)聽垃圾回收情況

node-memwatch

memwatch.on('stats',function(info){
  console.log(info)
})
memwatch.on('leak',function(info){
  console.log(info)
})

stats事件:每次進行全堆垃圾回收時,將觸發(fā)一次stats事件。這個事件將會傳遞內存統(tǒng)計信息。

{
"num_full_gc": 17, //第幾次全棧垃圾回收
"num_inc_gc": 8,  //第幾次增量垃圾回收
"heap_compactions": 8, //第幾次對老生代進行整理
"estimated_base": 2592568, //預估基數
"current_base": 2592568, //當前基數
"min": 2499912, //最小
"max": 2592568, //最大 
"usage_trend": 0 //使用趨勢
  }

觀察num_full_gc和num_inc_gc反映垃圾回收情況。

leak事件:如果經過連續(xù)5次垃圾回收后,內存仍然沒有被釋放,意味著內存泄漏的發(fā)生。這個時候會觸發(fā)一個leak事件。

{ start: Fri, 29 Jun 2012 14:12:13 GMT,
end: Fri, 29 Jun 2012 14:12:33 GMT,
growth: 67984,
reason: 'heap growth over 5 consecutive GCs (20s) - 11.67 mb/hr'
}

Heap Diffing 堆內存比較 排查內存溢出代碼。
下面,我們通過一個例子來演示如何排查定位內存泄漏:

首先我們創(chuàng)建一個導致內存泄漏的例子:

//app.js
var app = require('express')();
var http = require('http').Server(app);
var heapdump = require('heapdump');

var leakobjs = [];
function LeakClass(){
  this.x = 1;
}

app.get('/', function(req, res){
  console.log('get /');
  for(var i = 0; i < 1000; i++){
    leakobjs.push(new LeakClass());
  }
  res.send('<h1>Hello world</h1>');
});

setInterval(function(){
  heapdump.writeSnapshot('./' + Date.now() + '.heapsnapshot');
}, 3000);

http.listen(3000, function(){
  console.log('listening on port 3000');
});

這里我們通過設置一個不斷增加且不回被回收的數組,來模擬內存泄漏。

通過使用heap-dump模塊來定時紀錄內存快照,并通過chrome開發(fā)者工具profiles來導入快照,對比分析。

我們可以看到,在瀏覽器訪問 localhost:3000 ,并多次刷新后,快照的大小一直在增長,且即使不請求,也沒有減小,說明已經發(fā)生了泄漏。

接著我們通過過chrome開發(fā)者工具profiles, 導入快照。通過設置comparison,對比初始快照,發(fā)送請求,平穩(wěn),再發(fā)送請求這3個階段的內存快照。可以發(fā)現(xiàn)右側new中LeakClass一直增加。在delta中始終為正數,說明并沒有被回收。

小結

針對內存泄漏可以采用植入memwatch,或者定時上報process.memoryUsage內存使用率到monitor,并設置告警閥值進行監(jiān)控。

當發(fā)現(xiàn)內存泄漏問題時,若允許情況下,可以在本地運行node-heapdump,使用定時生成內存快照。并把快照通過chrome Profiles分析泄漏原因。若無法本地調試,在測試服務器上使用v8-profiler輸出內存快照比較分析json(需要代碼侵入)。

需要考慮在什么情況下開啟memwatch/heapdump??紤]heapdump的頻度以免耗盡了CPU。 也可以考慮其他的方式來檢測內存的增長,比如直接監(jiān)控process.memoryUsage()。

當心誤判,短暫的內存使用峰值表現(xiàn)得很像是內存泄漏。如果你的app突然要占用大量的CPU和內存,處理時間可能會跨越數個垃圾回收周期,那樣的話memwatch很有可能將之誤判為內存泄漏。但是,這種情況下,一旦你的app使用完這些資源,內存消耗就會降回正常的水平。所以需要注意的是持續(xù)報告的內存泄漏,而可以忽略一兩次突發(fā)的警報。

相關文章

  • VsCode與Node.js知識點詳解

    VsCode與Node.js知識點詳解

    在本篇文章中小編給大家分享了關于VsCode與Node.js的相關知識點以及安裝等內容,需要的朋友們可以參考下。
    2019-09-09
  • Node.js使用express寫接口的具體代碼

    Node.js使用express寫接口的具體代碼

    這篇文章主要介紹了Node.js使用express寫接口,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • 我的Node.js學習之路(四)--單元測試

    我的Node.js學習之路(四)--單元測試

    在專業(yè)化的軟件開發(fā)過程中,無論什么平臺語言,現(xiàn)在都需要UnitTest單元測試. Node.js有built-in的Assert。 今天讓我們來看一下Node.js的單元測試。在這兒我們使用nodeunit
    2014-07-07
  • node.js+express留言板功能實現(xiàn)示例

    node.js+express留言板功能實現(xiàn)示例

    本文介紹基于nodejs+express+art-template的留言板功能。包含列表界面、添加界面和發(fā)送留言功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • node.js中的buffer.Buffer.isBuffer方法使用說明

    node.js中的buffer.Buffer.isBuffer方法使用說明

    這篇文章主要介紹了node.js中的buffer.Buffer.isBuffer方法使用說明,本文介紹了buffer.Buffer.isBuffer的方法說明、語法、接收參數、使用實例和實現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • NodeJs通過async/await處理異步的方法

    NodeJs通過async/await處理異步的方法

    本篇文章主要介紹了NodeJs通過async/await處理異步的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • node.js實現(xiàn)微信JS-API封裝接口的示例代碼

    node.js實現(xiàn)微信JS-API封裝接口的示例代碼

    這篇文章主要介紹了node.js實現(xiàn)微信JS-API封裝接口的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • Node.js中的process.nextTick使用實例

    Node.js中的process.nextTick使用實例

    這篇文章主要介紹了Node.js中的process.nextTick使用實例,nextTick函數有什么用、怎么用、和setTimeout有什么區(qū)別呢,本文就講解了這些知識,需要的朋友可以參考下
    2015-06-06
  • NodeJS讀取分析Nginx錯誤日志的方法

    NodeJS讀取分析Nginx錯誤日志的方法

    這篇文章主要介紹了NodeJS讀取分析Nginx錯誤日志的相關知識,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-05-05
  • NodeJs實現(xiàn)定時任務的示例代碼

    NodeJs實現(xiàn)定時任務的示例代碼

    本篇文章主要介紹了NodeJs實現(xiàn)定時任務的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12

最新評論