2011-06-24 45 views
32

Düğüm uygulamamda bellek sızıntısı var gibi görünüyor. Hızlı bir şekilde yaptım ve JavaScript'im çok güçlü değil, bu yüzden bu kolay olabilir.Bellek sızıntısı socket.io + node.js

Üzerinde bir yığın döküntü yaptım ve bu 'nesne' dizesi mi? her 5 dakikada bir 1 MB oranında bellek sızdıran. String'i genişlettim ve aslında String.Array?

Öbek yığını: hayır müşterilerle, başlangıçta itibaren

  • : 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); 
        }); 
    

    Güncel sürüm Hala bellek sızıntısı, ancak yalnızca bu koşullar üzerinde görünüyor

    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; 
          }); 
        } 
    } 
    

    -> İnce

  • İnce> (hatta 1 istemci kesmek ve yeniden birlikte)
  • 2 istemci - -
  • 1 istemci bağlantısı> Leaking bellek
  • durdurun tüm bağlantıların -> İnce
  • 1 yeni bağlantı (bağlantı = 1) -> Kaçak bulunan bellek
+1

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

+7

'connectSync' :( – Raynos

+0

String.Array öğesini içerecek şekilde değiştirilmiş String'den bahsetmişsiniz, ve hatta bize bellek anlık görüntüsünüzde bunu işaret edin, ancak kodunuzda bunu kullanacak hiçbir şey görmedim, ne de String'i oluşturmak için ne yaptınız.Array – Matt

cevap

5

Kendinize bir iyilik yapın ve node-mysql kullanın, bu saf bir javascript mysql istemcisidir ve hızlıdır. Bunun dışında, çalışıyorken IO'nun engellenmesini durdurmak için eşzamansız kod kullanmalısınız. async kütüphanesini kullanarak size burada yardımcı olacaktır. Başka şeylerin arasında geçerek şelale geri çağırma kodu vardır.

Belleğinizin sızması ile ilgili olarak, muhtemelen birkaç ay içinde kullanmamasına rağmen, muhtemelen socket.io değil, binlerce eşzamanlı bağlantıya sahiptim ve bellek sızdırmıyordum ve kodum en iyisi de. Bununla birlikte, iki şey, ancak iki şeydir. Öncelikle kodunuz okunaklı değil. Kodunuzu düzgün bir şekilde biçimlendirmenizi öneririz (her girinti için iki boşluk kullanıyorum, ancak bazı kişiler dört kullanmaktadır). \r hat geri satırın başlangıcına okunacak neden olur

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

ve karakterleri üzerine: İkincisi, bağlantı sayısını baskı her yarım saatte gibi bir şey yapabileceğini zaman, biraz saçma görünüyor Orada, hattın yerini alacak ve çok miktarda geri kaydırma oluşturmayacak. Bu, hata ayıklama ayrıntılarını günlüğünüze koymayı seçerseniz, hata ayıklama konusunda yardımcı olacaktır.

Bellek kullanımını hızlı bir şekilde kontrol etmek için (veya ne kadar düğüm kullandığınızı düşündüğünüzde) process.memoryUsage() numaralı telefonu da kullanabilirsiniz.

+1

teşekkür ederiz. Şu anda socket.io'da bir bellek sızıntısı olduğuna inanılmasına rağmen - Bkz .: https://github.com/LearnBoost/socket.io/issues/299 – giggsey

0

İstemci bağlantısı kesildiğinde, bağlı istemciler dizinin düzgün şekilde temizlenememesiyle ilgili olabilir mi? Dizi değeri diziden düşürülmek yerine NULL olarak ayarlanır.