My chat works on 24 Threads (2x 6 cores X5650 @ 2.67GHz) ... if there are about 1000 connections CPU usage (on every thread) grows up to 80-100% .... I think that something is wrong with my code ... node shouldn't generate such load with only 1000 connections. Can you please give me some idea about where to look
My code:
express = require('express')
http = require('http');
cluster = require("cluster");
numCPUs = require("os").cpus().length,
port = 55678;
userCount = 0;
interv = false;
RedisStore = require("socket.io/lib/stores/redis"),
redis = require("socket.io/node_modules/redis"),
pub = redis.createClient(),
sub = redis.createClient(),
client = redis.createClient(),
counter = redis.createClient();
counter.set('count',0);
client.set('searching',0);
client.del('freeusers');
if (cluster.isMaster) {
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
}
else
{
app = express();
server = http.createServer(app).listen(port);
io = require('socket.io').listen(server);
io.configure(function () {
// io.set("transports", ["websocket"])
io.set("store", new RedisStore({
redisPub: pub,
redisSub: sub,
redisClient: client
})
);
io.set('log level', 0);
io.enable('browser client minification');
io.enable('browser client etag');
io.enable('browser client gzip');
});
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.php');
});
io.sockets.on('connection', function (socket){
var address = socket.handshake.address;
socket.set('options', JSON.stringify({'sex':'male','seek':'both'}));
socket.set('partner', 5);
socket.set('ip', address.address);
socket.emit('setsocket',socket.id);
counter.incr('count', function(err, newId){
userCount = newId;
socket.emit('people', userCount);
socket.broadcast.emit('people', userCount);
// console.log(Date(Date.now()) + ' Connected User ('+socket.id+' | '+address.address+':'+address.port+') '+userCount);
});
socket.ip = address.address;
socket.on('syscmd', function(cmd){
switch (cmd.cmd){
case 'new':
socket.set('options', JSON.stringify({'sex':cmd.sex,'seek':cmd.seek}));
socket.emit('updatechat', 'Poszukujemy dla Ciebie obcego, poczekaj ...');
socket.emit('setflag',1);
addNewUser(socket.id);
lookforpartner(socket.id);
break;
case 'reconnect':
socket.set('options', JSON.stringify({'sex':cmd.sex,'seek':cmd.seek}));
socket.get('partner', function(err, partner){
stopchat(socket.id,partner);
socket.emit('updatechat', 'Poszukujemy dla Ciebie obcego, poczekaj ...');
socket.emit('setflag',1);
addNewUser(socket.id);
lookforpartner(socket.id);
});
break;
default:
}
});
socket.on('sexchange', function (sex) {
socket.get('options',function(err,options){
socket.set('options', JSON.stringify({'sex':sex,'seek':options.seek}));
});
});
socket.on('seekchange', function (seek) {
socket.get('options',function(err,options){
socket.set('options', JSON.stringify({'sex':options.sex,'seek':seek}));
});
});
socket.on('updatechat', function(data){
socket.get('partner', function(err, partner) {
io.sockets.socket(partner).emit('updatechat',data);
});
socket.emit('updatechat',data);
});
socket.on('msgchat', function (data) {
socket.get('partner', function(err, partner) {
io.sockets.socket(partner).emit('msgchat',socket.id,data);
// console.log('Message between: '+socket.id+ ' AND '+partner+': '+data);
});
socket.emit('msgchat',socket.id , data);
});
socket.on('typing', function (data) {
socket.get('partner', function(err, partner){
io.sockets.socket(partner).emit('typing');
});
});
socket.on('stoptyping', function (data) {
socket.get('partner', function(err, partner){
io.sockets.socket(partner).emit('stoptyping');
});
});
socket.on('disconnect', function(){
var address = socket.handshake.address;
socket.get('partner', function(err, partner){
stopchat(socket.id,partner)
counter.decr('count', function(err, newId){
userCount = newId;
socket.broadcast.emit('people', userCount);
// console.log(Date(Date.now()) + ' Disconnected User ('+socket.id+' | '+address.address+':'+address.port+') '+userCount);
});
});
});
function removeUser(id)
{
client.srem('freeusers',id);
}
function addNewUser(id)
{
removeUser(id);
client.sadd('freeusers',id);
}
function lookforpartner(id)
{
// console.log('('+id+') searching ...')
client.get('searching',function(error,result){
if(parseInt(result) == 1)
{
return true;
}
else
{
client.smembers('freeusers',function(error,freeusers){
if(freeusers.length > 1)
{
client.set('searching',1);
partner = freeusers[Math.floor(Math.random()*freeusers.length)];
while(partner == id)
{
partner = freeusers[Math.floor(Math.random()*freeusers.length)];
}
socket.get('options',function(err,options){
options = JSON.parse(options);
if(err || options == null || typeof options != 'object' || !options.hasOwnProperty('seek') || !options.hasOwnProperty('sex'))
{
client.set('searching',0);
return false;
}
// console.log('partner: '+id+' (sex:'+options.sex+' and seek:'+options.seek+')');
io.sockets.socket(partner).get('options',function(err,poptions){
poptions = JSON.parse(poptions);
if(err || options == null || typeof poptions != 'object' || !poptions.hasOwnProperty('seek') || !poptions.hasOwnProperty('sex'))
{
removeGhost(partner);
client.set('searching',0);
return false;
}
// console.log('partner: '+partner+' (sex:'+poptions.sex+' and seek:'+poptions.seek+')');
if((options.seek == poptions.sex || options.seek == 'both') && (poptions.seek == options.sex || poptions.seek == 'both'))
{
// console.log('parred: '+partner+' (sex:'+poptions.sex+' and seek:'+poptions.seek+') AND '+id+' (sex:'+options.sex+' and seek:'+options.seek+')');
removeUser(partner);
removeUser(id);
io.sockets.socket(id).set('partner', partner);
io.sockets.socket(partner).set('partner', id);
io.sockets.socket(id).emit('chatunblock',1);
io.sockets.socket(partner).emit('chatunblock',1);
io.sockets.socket(id).emit('updatechat', 'Obcy podłączony, napisz Cześć :-)');
io.sockets.socket(partner).emit('updatechat', 'Obcy podłączony, napisz Cześć :-)');
}
client.set('searching',0);
});
});
}
});
}
});
}
function removeGhost(id)
{
console.log('Removing ghost: '+id);
removeUser(id);
io.sockets.socket(id).set('partner', 5);
io.sockets.socket(id).emit('disconnected','end');
}
function stopchat(id,partner)
{
removeUser(id);
if(partner != 5)
{
socket.set('partner', 5);
io.sockets.socket(partner).set('partner', 5);
io.sockets.socket(partner).emit('updatechat', 'Obcy wyszedł :-(');
io.sockets.socket(partner).emit('disconnected','end');
}
io.sockets.socket(id).emit('disconnected',2);
}
});
}