Подтвердить что ты не робот

Утечка памяти с помощью socket.io + node.js

Кажется, у меня есть утечка памяти с моим приложением node. Я быстро его построил, и мой JavaScript не слишком силен, поэтому это может быть легко.

Я сделал несколько кучи кучи на нем, и это объект String? утечка памяти, в размере около 1 МБ каждые 5 минут. Я расширил 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;
            });
    }
}

По-прежнему происходит утечка памяти, но, похоже, только в этих условиях:

  • При запуске без клиентов → Fine
  • Первое подключение клиента → Fine
  • Второй клиент (даже при отключении и повторном подключении первого клиента) → Утечка памяти
  • Остановить все соединения → Хорошо
  • 1 новое соединение (соединения = 1) → Утечка памяти
4b9b3361

Ответ 1

Сделайте себе одолжение и используйте node-mysql, это чистый клиент mysql javascript, и он быстро. Помимо этого, вы должны использовать асинхронный код, чтобы остановить блокировку IO во время работы. Использование библиотеки async поможет вам здесь. У этого есть код для обратного вызова водопада, проходящего между прочим.

Что касается утечки памяти, вероятно, это не socket.io, хотя я не использовал его через несколько месяцев, у меня было много тысяч одновременных подключений и не просочилась память, а мой код не был наилучшим образом.

Однако две вещи. Во-первых, ваш код неисправен. Я предлагаю правильно отформатировать код (я использую два пробела для каждого отступа, но некоторые используют четыре). Во-вторых, печать количества подключений каждые полчаса кажется немного глупым, когда вы можете сделать что-то вроде:

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

\r приведет к тому, что строка будет считана в начале строки и перезапишет там символы, которые заменят строку, а не создают огромное количество прокрутки. Это поможет при отладке, если вы решите разместить данные отладки при регистрации.

Вы также можете использовать process.memoryUsage() для быстрой проверки использования памяти (или сколько node считает, что вы используете).

Ответ 2

Может ли это быть связано с массивом подключенных клиентов, который не очищается должным образом, когда клиент отключается? Значение массива устанавливается равным NULL, а не удаляется из массива.