memwatch
test.js
var http = require('http');
var server = http.createServer(function (req, res) {
for (var i=0; i<1000; i++) {
server.on('request', function leakyfunc() {});
}
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
server.setMaxListeners(0);
console.log('Server running at http://127.0.0.1:1337/. Process PID: ', process.pid);
启动服务
-bash-4.1$ node test.js
Server running at http://127.0.0.1:1337/. Process PID: 12842
无限请求
-bash-4.1$ while true; do curl "http://127.0.0.1:1337/"; done
查看内存情况-bash-4.1$ top -12842
内存不断上涨
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12842 d 20 0 754m 123m 6296 R 97.3 3.4 0:30.25 node
安装memwatchnpm install --save memwatch
修改test.js
var http = require('http');
var memwatch = require('memwatch');
memwatch.on('leak', function(info) {
console.error('Memory leak detected: ', info);
});
var server = http.createServer(function (req, res) {
for (var i=0; i<1000; i++) {
server.on('request', function leakyfunc() {});
}
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
server.setMaxListeners(0);
console.log('Server running at http://127.0.0.1:1337/. Process PID: ', process.pid);
再重复上面操作,memwatch发现了内存泄漏就会输出这样
-bash-4.1$ node test.js
Server running at http://127.0.0.1:1337/. Process PID: 10640
Memory leak detected: { start: Tue Jul 07 2015 17:19:51 GMT+0800 (CST),
end: Tue Jul 07 2015 17:19:52 GMT+0800 (CST),
growth: 8157816,
reason: 'heap growth over 5 consecutive GCs (1s) - -2147483648 bytes/hr' }
Memory leak detected: { start: Tue Jul 07 2015 17:19:52 GMT+0800 (CST),
end: Tue Jul 07 2015 17:19:52 GMT+0800 (CST),
growth: 326688,
reason: 'heap growth over 5 consecutive GCs (0s) - -2147483648 bytes/hr' }
Memory leak detected: { start: Tue Jul 07 2015 17:19:52 GMT+0800 (CST),
end: Tue Jul 07 2015 17:19:53 GMT+0800 (CST),
growth: 2194336,
reason: 'heap growth over 5 consecutive GCs (1s) - -2147483648 bytes/hr' }
Heap Diffing 可以看某段代码的内内存泄漏情况
// Take first snapshot
var hd = new memwatch.HeapDiff();
// do some things ...
// Take the second snapshot and compute the diff
var diff = hd.end();
console.log(diff);
test.js:
var http = require('http');
var memwatch = require('memwatch');
var heapdump = require('heapdump');
var hd;
memwatch.on('leak', function(info) {
console.error(info);
if (!hd) {
hd = new memwatch.HeapDiff();
} else {
var diff = hd.end();
console.log(diff);
hd = null;
}
});
var server = http.createServer(function (req, res) {
for (var i=0; i<1000; i++) {
server.on('request', function leakyfunc() {
});
}
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
server.setMaxListeners(0);
console.log('Server running at http://127.0.0.1:1337/. Process PID: ', process.pid);
输出这样:
-bash-4.1$ node test.js
Server running at http://127.0.0.1:1337/. Process PID: 23138
{ start: Tue Jul 07 2015 19:40:34 GMT+0800 (CST),
end: Tue Jul 07 2015 19:40:34 GMT+0800 (CST),
growth: 8009744,
reason: 'heap growth over 5 consecutive GCs (0s) - -2147483648 bytes/hr' }
{ start: Tue Jul 07 2015 19:40:35 GMT+0800 (CST),
end: Tue Jul 07 2015 19:40:35 GMT+0800 (CST),
growth: 325648,
reason: 'heap growth over 5 consecutive GCs (0s) - -2147483648 bytes/hr' }
{ before:
{ nodes: 141391,
time: Tue Jul 07 2015 19:40:34 GMT+0800 (CST),
size_bytes: 13936304,
size: '13.29 mb' },
after:
{ nodes: 146593,
time: Tue Jul 07 2015 19:40:35 GMT+0800 (CST),
size_bytes: 14040744,
size: '13.39 mb' },
change:
{ size_bytes: 104440,
size: '101.99 kb',
freed_nodes: 3269,
allocated_nodes: 8471,
details:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ] } }
{ start: Tue Jul 07 2015 19:40:36 GMT+0800 (CST),
end: Tue Jul 07 2015 19:40:36 GMT+0800 (CST),
growth: 1785744,
reason: 'heap growth over 5 consecutive GCs (0s) - -2147483648 bytes/hr' }
heapdump
安装heapdumpnpm install heapdump
人家文档说了Node是v0.6 or v0.8的话要装这个版本npm install heapdump@0.1.0
修改test.js:
var http = require('http');
var memwatch = require('memwatch');
var heapdump = require('heapdump');
memwatch.on('leak', function(info) {
console.error('Memory leak detected: ', info);
var file = '/data/home/dongshaoshuai/memleak/' + process.pid + '-' + Date.now() + '.heapsnapshot';
heapdump.writeSnapshot(file, function(err){
if (err) {
console.error(err);
} else {
console.error('Wrote snapshot: ' + file);
}
});
});
var server = http.createServer(function (req, res) {
for (var i=0; i<1000; i++) {
server.on('request', function leakyfunc() {});
}
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
server.setMaxListeners(0);
console.log('Server running at http://127.0.0.1:1337/. Process PID: ', process.pid);
再来无限请求:
while true; do curl "http://127.0.0.1:1337/"; done
输出这样:
-bash-4.1$ node test.js
Server running at http://127.0.0.1:1337/. Process PID: 3034
Memory leak detected: { start: Tue Jul 07 2015 17:56:39 GMT+0800 (CST),
end: Tue Jul 07 2015 17:56:40 GMT+0800 (CST),
growth: 8020976,
reason: 'heap growth over 5 consecutive GCs (1s) - -2147483648 bytes/hr' }
Wrote snapshot: /data/home/dongshaoshuai/memleak/3034-1436263000668.heapsnapshot
Memory leak detected: { start: Tue Jul 07 2015 17:56:41 GMT+0800 (CST),
end: Tue Jul 07 2015 17:56:41 GMT+0800 (CST),
growth: 326496,
reason: 'heap growth over 5 consecutive GCs (0s) - -2147483648 bytes/hr' }
Wrote snapshot: /data/home/dongshaoshuai/memleak/3034-1436263001402.heapsnapshot
会在指定目录生成heapsnapshot文件,每次发生内存泄漏都会写入一个新的heapsnapshot文件
.. (up a dir)
/data/home/dongshaoshuai/memleak/
3034-1436263000668.heapsnapshot
3034-1436263001402.heapsnapshot
test.js
将3034-1436263000668.heapsnapshot
复制到windows下,用Chrome浏览器的Profile
功能打开i此文件
将文件load进来,就可以看到内存泄漏情况