Node.jsnetworking套接字内存泄漏?

我有这个脚本 。

var net = require("net") , heapdump = require("heapdump"); function onConnection (client) { client.on("data", function (data) { client.end(); }); }; function onListen () { var socket = net.connect({host: "127.0.0.1", port: 3000}); socket.bigBuffer = new Buffer(50000000); //50MB Buffer heapdump.writeSnapshot(__dirname + "/initial.heapsnapshot", function writeInitialSnapshot () { console.log("Wrote initial heap snapshot"); socket.write("data"); }); socket.on("close", function () { writeEndSnapshot(); }); }; function writeEndSnapshot () { setTimeout(function () { console.log("Running GC"); gc(); heapdump.writeSnapshot(__dirname + "/final.heapsnapshot", function writeFinalSnapshot () { console.log("Wrote final heap snapshot"); }); }, 1000); }; net.createServer(onConnection).listen(3000, onListen); 

test.js的作用非常简单:

它创build一个networking服务器,在收到任何数据后立即closures客户端,并将其绑定到本地主机的端口3000 。 当服务器进行侦听时,会执行onListen函数,它会实例化一个连接到服务器的socket ,然后获取堆快照(请注意,在第13行中,我们将一个50MB bigBuffer设置到套接字上,这只是为了方便查找它在堆快照中)

writeEndSnapshot获得初始快照之后, sockets将一些数据写入服务器并结束,这是writeEndSnapshot函数被执行的时候,等待下一个tick,强制GC(垃圾收集)循环,然后把最后一个堆快照。

对我来说,看起来很清楚,在拍摄最终快照的时候,套接字应该已经被丢弃了,因此被垃圾收集了。 但是,当我加载快照时,这并不是我在Google Chrome的分析器中看到的。

初始堆快照

在这里输入图像描述

最后的堆快照

在这里输入图像描述

正如你在最后的快照中看到的, bigBuffer仍然由socket 。 我不知道为什么socket还活着。 所有我可以在socket owner in TCP @27447之后的retainers树中看到。 你认为这可能是一个节点的错误?

我真的很感激任何帮助,了解发生了什么事情。

谢谢!

事实certificate,如果只有一个客户端套接字,这不会得到垃圾回收。 这里有一个更新的脚本现在有两个套接字:

 var net = require("net") , heapdump = require("heapdump"); function onConnection (client) { client.on("data", function (data) { client.end(); }); }; function onListen () { var socket , sockets = [] , closedSockets = 0; for (var i = 0; i < 2; i++) { socket = net.connect({host: "127.0.0.1", port: 3000}); sockets.push(socket); socket.bigBuffer = new Buffer(25000000); //25MB Buffer socket.on("close", function () { if (++closedSockets == sockets.length) { writeEndSnapshot(); }; }); }; heapdump.writeSnapshot(__dirname + "/initial.heapsnapshot", function () { console.log("Wrote initial heap snapshot"); for (var i = 0; i < sockets.length; i++) { sockets[i].write("data"); }; }); }; function writeEndSnapshot () { setTimeout(function () { console.log("Running GC"); gc(); heapdump.writeSnapshot(__dirname + "/final.heapsnapshot", function () { console.log("Wrote final heap snapshot"); }); }, 1000); }; net.createServer(onConnection).listen(3000, onListen); 

现在一切正常。 但是,如果您更改循环以仅实例化一个套接字,则会看到它在堆中保持活动状态。