Socket.io和node.js,不能理解内存使用情况

我目前在我的服务器上使用socket.io v1.4.2和node.js v0.10.29。 我试图跟踪我的应用程序中的内存泄漏,我不知道,但我认为socket.io是我的问题的一部分。

所以这里的服务器代码(演示例子):

var server = require ('http').createServer (); var io = require ('socket.io')(server); io.on ("connection", function (socket) { socket.on ('disconnect', function (data) { /* Do nothing */ }); }); 

第一步:内存:58Mb

第2步:我创build了很多客户端(〜10000),内存:300 Mb

第三步:closures所有的客户,等待GC的工作

第四步:我看看我的记忆:100 Mb:'(

步骤5:与步骤2和3相同

第6步:内存160Mb …

等等,记忆不断增长。

我认为GC是懒惰的,所以我重试了下面的代码:

 setInterval (function () { global.gc (); }, 30000); 

我开始我的app.js:

 node --expose-gc app.js 

但是我有同样的结果。

最后我试试

 var server = require ('http').createServer (); var io = require ('socket.io')(server); clients = {}; io.on ("connection", function (socket) { clients[socket.id] = socket; socket.on ('disconnect', function (data) { delete clients[socket.id]; }); }); 

我有同样的结果。 我怎样才能释放这个记忆?

编辑

我直接在我的主要来源创build快照。

我使用以下命令安装新模块:

  npm install heapdump 

我在我的代码中写道:

  heapdump = require ('heapdump'); setInterval (function () { heapdump.writeSnapshot (); }, 30000); 

它每30秒就把程序的heapdump,并保存在当前目录。 我阅读了Chrome的模块“configuration文件”的heapdump。

所以,问题可能是socket.io,因为我发现许多string没有发布,我用socket发射。 也许我不会以正确的方式写出排放? 我这样做:

  var data1 = [1, 2, 3]; var data2 = [4, 5, 6]; var data3 = [7, 8, 9]; socket.emit ('b', data1, data2, data3); data1 = []; data2 = []; data3 = []; 

在我的快照中说,程序保留下列string:“b [1,2,3] [4,5,6] [7,8,9]”在我的记忆,百万计时间我想做?

我也做了另一个(也许愚蠢?)testing:

  var t1 = new Date (); ... var t2 = new Date (); var data1 = [1, 2, 3]; var data2 = [4, 5, 6]; var data3 = [7, 8, 9]; socket.emit ('b', data1, data2, data3); data1 = []; data2 = []; data3 = []; console.log ("LAG: " + t2 - t1); t1 = new Date (); 

我有这个结果:

  LAG: 1 LAG: 1 ... LAG: 13 LAG: 2 LAG: 26 LAG: 3 ... LAG: 100 LAG: 10 LAG: 1 LAG: 1 LAG: 120 ... keeps growing 

编辑2:

这是我的整个testing代码:

 /* Make snapshot every 30s in current directory */ heapdump = require ('heapdump'); setInterval (function () { heapdump.writeSnapshot (); }, 30000); /* Create server */ var server = require ('http').createServer (); var io = require ('socket.io')(server); var t1 = new Date (); clients = {}; io.on ("connection", function (socket) { clients[socket.id] = socket; socket.on ('disconnect', function (data) { delete clients[socket.id]; }); }); setInterval (function () { var t2 = new Date (); for (c in clients) { var data1 = [1, 2, 3]; var data2 = [4, 5, 6]; var data3 = [7, 8, 9]; clients[c].emit ('b', data1, data2, data3); data1 = []; data2 = []; data3 = []; } console.log ("LAG: " + t2 - t1); t1 = new Date (); }, 100); 

我不给客户端的代码。 因为我假设:如果问题出在客户端,那么这是一个安全问题。 事实上,这将是一个简单的方法来饱和服务器的RAM。 所以这是一种更好的DDOS,我希望问题不在客户端。

根据您包含的服务器代码进行编辑

在你的服务器上:

 c.emit ('b', data1, data2, data3);` 

应改为:

 clients[c].emit('b', data1, data2, data3); 

c.emit()可能引发exception,因为csocket.idstring,string没有.emit()方法。

原始答案

你需要确定的是,内存的增长是否实际上是在node.js堆中分配的内存,还是没有返回到操作系统的可用内存,并且可以在node.js中重用? 测量node.js过程使用的内存对于查看从系统中获取的内容非常有用,并且不应该随着时间的推移而不断地上升,但是它并不会告诉你内部的真实情况。

仅供参考,只要您的node.js应用程序有几个空闲周期,您不应该手动调用GC。 它会自己做。

测量node.js堆内使用内容的常用方法是创build堆快照,运行步骤1-4,创build堆快照,再次运行这些步骤,创build另一个堆快照,区分快照并查看在node.js堆中的内存实际上是两个状态的不同。

这将向您显示在node.js中实际正在使用的内容。

这里有一篇关于获取堆快照并在debugging器中读取它们的文章: https : //strongloop.com/strongblog/how-to-heap-snapshots/