在几种情况下,nodejs内存泄漏

时间:2013-06-04 03:58:03

标签: javascript node.js memory v8

  1. 原始本机tcp服务器 我使用客户端测试代码来并发长连接服务器,什么都不做。 在5w conncetions之后我关闭了client.js,但服务器端将有大约100M内存不释放。
  2. 服务器代码:

    var net = require('net');
    var server = net.createServer(function(client) {
      console.log('server connected');
      client.on('data',function(){});
      client.on('end',function(){console.log('end');});
    
    });
    server.listen(8124, function() {
      console.log('server bound');
    });
    

    客户端代码:

    var net = require('net');
    var host = '192.168.0.110'
    // var host = "localhost"
      , port = 8124
    
    
    for(var i=0; i < 50000; i++){
      var client = net.connect({host: host, port: port},
          function(i){
           return function() { //'connect' listener
               var num = i;
               console.log('client connected ' + num);
          }}(i)
      );
      client.on('end',function(){
            console.log('end');
            client.end()
      })
    }
    

    客户端在另一台机器上

    2,长循环

     var a = b = c = d = [];
     console.log((process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2), 'Mb');
    
     for(i=0;i<50000;i++){
         a.push(new Date());
         b.push(new Date());
         c.push(new Date());
         d.push(new Date());
    
     }
     console.log((process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2), 'Mb');
       a = null;
       b = null;
       c = null;
       d = null;
    
     console.log('null');
     console.log((process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2), 'Mb');
    
     console.log((process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2), 'Mb');
     setInterval(function(){
       console.log((process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2), 'Mb');
     },5000);
    

    我将变量设置为null但内存不释放。 有人告诉我使用process.nextTick来防止长循环 但它仍然不起作用。

2 个答案:

答案 0 :(得分:2)

取消分配引用并将其设置为null后,不会立即释放内存。如果要强制GC在给定时刻执行:

  1. 使用--expose-gc
  2. 启动节点

    node --expose-gc test.js

    1. 在您的代码中添加gc:
    2. 的调用

      global.gc();

      你不应该在生产中这样做,因为V8自己处理GC调用并且非常好。

答案 1 :(得分:0)

您的客户端js存在问题:

client.on('end', function() {
    console.log('end');
    client.end()
})

此事件将在连接结束后发生,您可以通过调用.end()来完成...所以最后调用.end()没有任何意义事件。此外,您根本没有关闭连接:

var client = net.connect({
    host: host,
    port: port
}, function(i) {
    return function() { //'connect' listener
        var num = i;
        console.log('client connected ' + num);
        this.end() //Close the connection
    }
}(i));

在修复之后我可以毫无例外地运行你的代码,并且它没有泄漏给我。

服务器代码:

function getUsed() {
    return process.memoryUsage().heapUsed;
}
var startedWith;
var net = require('net');
var server = net.createServer(function(client) {
    client.on('data', function() {});
    client.on('end', function() {
        console.log("end");
    });
});
server.listen(8124, function() {
    startedWith = getUsed();
});
setInterval(function() {
    gc();
}, 13);
setInterval(function() {
    gc();
    console.log(getUsed() - startedWith);
}, 250)

使用节点0.10 $ node --expose-gc server.js

运行

客户代码:

var net = require('net');
var host = 'localhost',
    port = 8124
for (var i = 0; i < 1500; i++) {
    var client = net.connect({
        host: host,
        port: port
    },

    function(i) {
        return function() { //'connect' listener
            var num = i;
            console.log('client connected ' + num);
            this.end();
        }
    }(i));
    client.on('end', function() {
        console.log('end');
    })
}

在服务器运行后使用节点0.10 $ node client.js运行。