javascript - تسرب الذاكرة مع socket.io+node.js




(2)

هل نفسك صالح واستخدام عقدة ميسكل ، انها عميل جافاسكريبت ميسكل النقي وانها سريعة. بخلاف ذلك، يجب أن تستخدم رمز غير متزامن لإيقاف إو تم حظره أثناء العمل. استخدام مكتبة غير المتزامنة سوف تساعدك هنا. لديها رمز لشلال رد الاتصال يمر بين أمور أخرى.

أما بالنسبة للذاكرة الخاصة بك تسرب، فإنه على الأرجح ليس socket.io، على الرغم من أنني لم تستخدم في غضون بضعة أشهر، لقد كان العديد من الآلاف من الاتصالات المتزامنة وليس تسربت الذاكرة، وكان بلدي ليس أفضل إما.

شيءان، ومع ذلك. أولا التعليمات البرمجية الخاصة بك غير قابلة للقراءة الفيلي. أقترح النظر في تنسيق التعليمات البرمجية بشكل صحيح (يمكنني استخدام مسافتين لكل المسافة البادئة ولكن بعض الناس استخدام أربعة). ثانيا، طباعة عدد من الاتصالات كل نصف ساعة يبدو سخيفة قليلا، عندما كنت يمكن أن تفعل شيئا مثل:

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

و \r سوف يتسبب في قراءة الخط إلى بداية السطر والكتابة الأحرف هناك، والتي سوف تحل محل الخط وليس إنشاء كمية كبيرة من التمرير. وهذا سوف يساعد مع التصحيح إذا اخترت وضع تفاصيل التصحيح في التسجيل الخاص بك.

يمكنك أيضا استخدام process.memoryUsage() للتحقق بسرعة من استخدام الذاكرة (أو كم العقدة تعتقد أنك تستخدم).

يبدو أن هناك تسرب الذاكرة مع تطبيق العقدة بلدي. لقد بنيت بسرعة، وجافا سكريبت ليست قوية جدا، لذلك قد يكون هذا سهلا.

لقد فعلت بعض كومة كومة على ذلك، وانها سلسلة "كائن"؟ تسرب الذاكرة، بمعدل حوالي 1MB كل 5 دقائق. أنا الموسعة سلسلة، وانها في الواقع 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;
            });
    }
}

لا يزال تسرب الذاكرة، ولكن يبدو فقط على هذه الشروط:

  • من بدء التشغيل، مع عدم وجود عملاء -> غرامة
  • اتصال العميل الأول -> غرامة
  • العميل الثاني (حتى مع فصل العميل 1ST وإعادة الاتصال) -> تسرب الذاكرة
  • وقف جميع الاتصالات -> غرامة
  • 1 اتصال جديد (اتصالات = 1) -> تسرب الذاكرة

هل يمكن أن يكون هذا مرتبطا بمصفوفة العملاء المتصلين التي لا يتم مسحها بشكل صحيح عند فصل العميل؟ يتم تعيين قيمة الصفيف إلى نول بدلا من إسقاطها من المصفوفة.





socket.io