2011-06-24 13 views
32

Parece que tengo una pérdida de memoria con la aplicación de mi nodo. Lo construí rápidamente, y mi JavaScript no es demasiado fuerte, así que esto podría ser fácil.Pérdida de memoria con socket.io + node.js

He hecho algunos volcados del montón, ¿y es el 'objeto' String? filtración de memoria, a razón de aproximadamente 1 MB cada 5 minutos. Expandí String, y en realidad es String.Array?

pila Montón: 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); 
    }); 

versión actual

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

continúan las fugas de memoria, pero parece que sólo en estas condiciones:

  • Desde el inicio, sin clientes -> Fino
  • primera conexión de cliente -> Bella
  • segundo cliente (incluso con la primera desconexión cliente y volver a conectar) -> Fuga de memoria
  • Detener todas las conexiones -> Bellas
  • 1 nueva conexión (conexiones = 1) -> La fuga memoria
+1

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

+7

'connectSync' :( – Raynos

+0

Menciona que ha modificado String para que contenga String.Array, e incluso apúntanos a eso en tu instantánea de memoria, pero no veo nada en tu código que use esto, ni lo que hiciste para crear String.Array – Matt

Respuesta

5

Hazte un favor y usa node-mysql, es un cliente javascript mysql puro y es rápido. Aparte de eso, deberías estar usando un código asíncrono para evitar que IO se bloquee mientras trabajas. Usar la biblioteca async lo ayudará aquí. Tiene un código para pasar la devolución de llamada en cascada, entre otras cosas.

En cuanto a la pérdida de memoria, probablemente no sea socket.io, aunque no lo he usado en unos pocos meses, he tenido muchos miles de conexiones simultáneas y no se ha filtrado la memoria, y mi código no era el mejor tampoco.

Dos cosas, sin embargo. En primer lugar, su código es ilegible. Sugiero buscar el formato correcto de tu código (uso dos espacios para cada sangrado, pero algunas personas usan cuatro). En segundo lugar, la impresión del número de conexiones cada media hora parece un poco tonto, cuando se podría hacer algo como:

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

El \r hará que la línea que se lee de nuevo al comienzo de la línea y sobrescribir los caracteres allí, que reemplazará la línea y no creará una gran cantidad de desplazamiento. Esto ayudará con la depuración si elige poner detalles de depuración en su registro.

También puede usar process.memoryUsage() para comprobar rápidamente el uso de memoria (o la cantidad de nodos que piensa que está utilizando).

+1

Gracias. Aunque actualmente se cree que es una pérdida de memoria en socket.io - Ver: https://github.com/LearnBoost/socket.io/issues/299 – giggsey

0

¿Podría estar esto relacionado con la matriz de clientes conectados que no se borra correctamente cuando un cliente se desconecta? El valor de la matriz se establece en NULL en lugar de ser eliminado de la matriz.