2011-06-24 17 views
32

ノードアプリケーションでメモリリークが発生しているようです。私はそれを素早く構築しました。私のJavaScriptはあまり強くないので、これは簡単かもしれません。socket.io + node.jsを使用したメモリリーク

ヒープダンプを実行しましたが、それは文字列 'オブジェクト'ですか? 5分ごとに約1MBの割合でメモリをリークします。私はStringを拡張しました。実際はStringです.Array?

ヒープスタック:なしクライアントと、スタートアップから

  • http://i.imgur.com/ZaBp0.png

    #!/usr/local/bin/node 
    
    var port = 8081; 
    
    var io = require('socket.io').listen(port), 
    sys = require('sys'), 
    daemon = require('daemon'), 
    mysql = require('mysql-libmysqlclient'); 
    
    var updateq = "SELECT 1=1"; 
    var countq = "SELECT 2=2"; 
    
    io.set('log level', 2); 
    
    
    process.on('uncaughtException', function(err) { 
        console.log(err); 
    }); 
    
    var connections = 0; 
    
    var conn = mysql.createConnectionSync(); 
    dbconnect(); 
    
    io.sockets.on('connection', function(client){ 
        connections++; 
        client.on('disconnect', function(){ connections--; }) 
    }); 
    
    process.on('exit', function() { 
        console.log('Exiting'); 
        dbdisconnect(); 
    }); 
    
    function dbdisconnect() { 
        conn.closeSync(); 
    } 
    
    function dbconnect() { 
        conn.connectSync('leet.hacker.org','user','password'); 
    } 
    
    
    function update() { 
        if (connections == 0) 
         return; 
        conn.query(updateq, function (err, res) { 
         if (err) { 
         dbdisconnect(); 
         dbconnect(); 
         return; 
         } 
         res.fetchAll(function (err, rows) { 
         if (err) { 
          throw err; 
         } 
         io.sockets.json.send(rows); 
         }); 
        }); 
    } 
    
    function totals() { 
        if (connections == 0) 
         return; 
         conn.query(countq, function (err, res) { 
          if (err) { 
         // Chances are that the server has just disconnected, lets try reconnecting 
         dbdisconnect(); 
         dbconnect(); 
          throw err; 
          } 
          res.fetchAll(function (err, rows) { 
          if (err) { 
           throw err; 
          } 
         io.sockets.json.send(rows); 
          }); 
         }); 
    
    } 
    
    setInterval(update, 250); 
    setInterval(totals,1000); 
    
    setInterval(function() { 
    console.log("Number of connections: " + connections); 
    },1800000); 
    
    
    
        daemon.daemonize('/var/log/epiclog.log', '/var/run/mything.pid', function (err, pid) { 
        // We are now in the daemon process 
        if (err) return sys.puts('Error starting daemon: ' + err); 
    
        sys.puts('Daemon started successfully with pid: ' + pid); 
        }); 
    

    最新バージョンそれでもメモリリークが、それだけで、これらの条件に思わ

    function totals() { 
    
         if (connections > 0) 
         { 
           var q = "SELECT query FROM table"; 
    
          db.query(q, function (err, results, fields) { 
          if (err) { 
            console.error(err); 
            return false; 
          } 
    
          for (var row in results) 
          { 
            io.sockets.send("{ ID: '" + results[row].ID + "', event: '" + results[row].event + "', free: '" + results[row].free + "', total: '" + results[row].total + "', state: '" + results[row]$ 
            row = null; 
          } 
    
    
          results = null; 
          fields = null; 
          err = null; 
          q = null; 
          }); 
        } 
    } 
    

    - >ファイン

  • 第一クライアント接続 - >(でも、第一のクライアントの切断と再接続を持つ)ファイン
  • 第二のクライアント - >メモリリーク
  • ストップすべての接続 - >ファイン
  • 1新しい接続(コネクション= 1) - >が漏れますメモリ
+1

参考:http://stackoverflow.com/questions/5733665/how-to-prevent-memory-leaks-in-node-js –

+7

'connectSync' :( – Raynos

+0

あなたはString.Arrayを含むように修正されたStringを記述しますが、あなたのメモリスナップショットでもそれを指摘していますが、これを使用するコードや、String.Arrayを実際に作成したものは何も見つかりません。 – Matt

答えて

5

node-mysqlを使用してください。純粋なjavascript mysqlクライアントです。高速です。それ以外の場合は、作業中にIOがブロックされないように非同期コードを使用する必要があります。 asyncライブラリを使用すると、ここで役立ちます。それは、他のものの中で滝コールバックを渡すためのコードを持っています。

あなたのメモリが漏れているのは、おそらくsocket.ioではありませんが、私は数ヶ月で使用していませんが、何千もの同時接続があり、メモリが漏れていませんでした。どちらも最高です。

ただし、2つのことがあります。まず、あなたのコードは失敗して読めなくなります。私はあなたのコードを適切にフォーマットすることを検討します(私はすべての字下げに2つのスペースを使いますが、4人を使用する人もいます)。 \rは、バックラインの先頭に行が読み出されないことが文字を上書きします

setInterval(function() { 
    process.stdout.write('Current connections: ' + connections + '  \r'); 
}, 1000); 

:第二に、接続数を印刷すると、すべての半分の時間は次のようにあなたが何かをすることができたときに、少し愚かなようです行を置き換えて、大量のスクロールバックを作成しません。これは、ロギングにデバッグの詳細を入れることを選択した場合、デバッグに役立ちます。

process.memoryUsage()を使用して、メモリ使用量(または使用していると思うノードの量)を素早く確認することもできます。

+1

ありがとう。現在、socket.ioのメモリリークと考えられていますが - https://github.com/LearnBoost/socket.io/issues/299を参照してください。 – giggsey

0

これは、クライアントの接続が切断されたときに接続されたクライアントアレイが適切に消去されないことに関連していますか?配列の値は配列から削除されるのではなく、NULLに設定されます。

関連する問題