8

Node.js排除内存泄漏演示

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzUxNjk4ODMzOA%3D%3D&%3Bmid=2247483764&%3Bidx=1&%3Bsn=ce2e0e3110f396965afc82621edcd4b1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

用于定位node内存泄漏的工具常用的有:

v8-profiler [1] node-heapdump [2] node-memwatch [3]

在演示DEMO之前可以了解点基本前置知识

关于Node的堆内存与堆外内存小记。

1. 受到V8 GC的主要是堆内存。 2. Node中的内存并非都是通过V8来进行分配的,可通过堆中的内存用量(heapUsed)总是小于进程常驻内存(rss)看出。对于那些不是通过V8来分配内存的我们称为堆外内存,比如Buffer,Buffer是基于C++的不是V8(从下面的demo中rss与external的值可以看出)。external代表 V8 管理的,绑定到 Javascript 的 C++ 对象的内存使用情况。 3. 因此表明堆外内存是可以突破内存限制问题。

FZBNZnR.jpg!web

uiuyeay.jpg!web

2yqiIvI.jpg!web

UZnaI3U.jpg!web

使用node-heapdump排除内存泄漏的DEMO

这里主要演示node-heapdump, node-memwatch很久没有维护了。

环境安装

node.js node-gyp mac下需要安装 xcode-select --install mac下安装xcode后 sudo xcode-select --switch /Library/Developer/CommandLineTools/ node-heapdump

代码


const heapdump = require('heapdump')

const http = require('http')


const leakArray = []

const leak = function() {

leakArray.push(`leak: ${Math.random()}`)

}


http.createServer(function(req, res) {

// 每次访问node服务。都会往leakArray增加数据,并且不会回收。

leak()

res.writeHead(200, {'Content-Type': 'text/plain'})

res.end('hello node')

}).listen(9999)


console.log('server is running at: http:127.0.0.1:9999/')

然后我们通过在终通过curl不断访问服务器curl http://127.0.0.1:9999模拟用户访问,这个时候leakArray数组不断增大,并且不会被回收。

在UNIX平台上,你可以向服务器进程通发送SIGUSR2信号强制快照。


$ kill -USR2 <pid>

mac下查看pid

$ lsof -i tcp:9999

这个时候会在你的文件夹生成一个快照,文件名格式默认为:heapdump- . .heapsnapshot。

2YJFBrA.jpg!web

由于Node是依赖V8引擎执行JavaScript的,Chrome浏览器也是,所以我们可以借助Chrome开发者工具中的Memory模块来分析这些dump文件。首先打开Chrome的开发者工具,切换到Memory,并依次加载dump文件。

zmiYnuE.jpg!web

关于Summary这个选项,从图中可以看出它有Constructor、Distance、Shallow Size、Retained Size共4项。Constructor这列是用类名对变量进行分组;Distance表示和根对象的距离,越小表示和根对象越近;Shallow Size表示变量自身的大小,不包含它引用的变量的大小;Retained Size不仅包含自身的大小,还包含了引用的变量的大小。

从图中可以看出,(string)那一行的Shallow Size和Retained Size都占据了100%的内存。

我们直接查看distance(20)最远的那一行。

VzYJfeJ.jpg!web

然后我们详情看下leak()。

NzEFv2q.jpg!web

当你再详细查看leakArray你就发现这里存储了大量的leak字符串,它们一直未得到回收。

Z7vauuy.jpg!web

参考资料

深入浅出node.js

PS:感兴趣的可以关注下公众号。

f6RV3ib.png!web

References

[1] v8-profiler:  https://github.com/node-inspector/v8-profiler

[2] node-heapdump:  https://github.com/bnoordhuis/node-heapdump

[3] node-memwatch:  https://github.com/lloyd/node-memwatch


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK