WebSocket-Node
WebSocket-Node copied to clipboard
WebSocketConnection issue
Does this cause memory leaks, when send many messages in same connection? I add 2 lines into memoryleak-client.js, it seems cause memoryleak-server leaks?
function maybeScheduleSend(i) {
var client = deviceList[i];
var random = Math.round(Math.random() * 100);
console.log(i + ' - scheduling send. Random: ' + random);
if (random < 50) {
setTimeout(function() {
console.log(i + ' - send timeout. Connected? ' + client.connection.connected);
if (client && client.connection.connected) {
console.log(i + ' - Sending test data! random: ' + random);
+ for ( var i = 0; i<10000; ++i){
client.connection.send( (new Array(random)).join('TestData') );
+ }
}
}, random);
}
}
I remember I found many part of BufferList pieces in coredump of our production nodejs, maybe relative to #139. I'm not convinced about this.
Node v5.7.1
I add some test cases here,
memoryleak-server.js
var fs = require('fs');
var WebSocketServer = require('../../lib/websocket').server;
var https = require('http');
var server = https.createServer();
server.listen(8080, function() {
console.log((new Date()) + ' Server is listening on port 8080 (ws)');
});
var wsServer = new WebSocketServer({
httpServer: server,
autoAcceptConnections: true
});
wsServer.on('connect', function(connection) {
connection.on('message', function(message) {
if (message.type === 'utf8') {
connection.sendUTF(message.utf8Data);
}
});
});
setInterval( function(){
global.gc();
console.log(mb(process.memoryUsage().rss));
}, 5000 );
function mb(val) {
return Math.round(val / (1024 * 1024)) + " MB";
}
memoryleak-client-buggy.js
var WebSocketClient = require('../../lib/websocket').client;
// buggy client
connect( 3000000 );
function connect( msg_cnt ){
var client = new WebSocketClient();
client.on('connect', function(connection) {
send(connection, msg_cnt);
});
client.connect('ws://localhost:8080');
}
function send(conn, msg_cnt) {
var msg = new Array(100).join('A');
for(var i = 0; i < msg_cnt; ++i){
conn.send(msg);
}
setTimeout(function(){
conn.close();
}, 10 * 1000)
}
memoryleak-client-normal.js
var WebSocketClient = require('../../lib/websocket').client;
var connectionAmount = process.argv[2];
var activeCount = 0;
var deviceList = [];
connectDevices();
function logActiveCount() {
console.log('---activecount---: ' + activeCount);
}
setInterval(logActiveCount, 500);
function connectDevices() {
for( var i=0; i < connectionAmount; i++ ){
connect( i );
}
}
function connect( i ){
// console.log( '--- Connecting: ' + i );
var client = new WebSocketClient({
});
client._clientID = i;
deviceList[i] = client;
client.on('connectFailed', function(error) {
console.log(i + ' - connect Error: ' + error.toString());
});
client.on('connect', function(connection) {
console.log(i + ' - connect');
activeCount ++;
client.connection = connection;
flake( i );
maybeScheduleSend(i);
connection.on('error', function(error) {
console.log(i + ' - ' + error.toString());
});
connection.on('close', function(reasonCode, closeDescription) {
console.log(i + ' - close (%d) %s', reasonCode, closeDescription);
activeCount --;
if (client._flakeTimeout) {
clearTimeout(client._flakeTimeout);
client._flakeTimeout = null;
}
connect(i);
});
connection.on('message', function(message) {
if ( message.type === 'utf8' ) {
console.log(i + ' received: \'' + message.utf8Data + '\'');
}
});
});
client.connect('ws://localhost:8080');
}
function disconnect( i ){
var client = deviceList[i];
if (client._flakeTimeout) {
client._flakeTimeout = null;
}
client.connection.close();
}
function maybeScheduleSend(i) {
var client = deviceList[i];
var random = Math.round(Math.random() * 100);
console.log(i + ' - scheduling send. Random: ' + random);
if (random < 50) {
setTimeout(function() {
console.log(i + ' - send timeout. Connected? ' + client.connection.connected);
if (client && client.connection.connected) {
console.log(i + ' - Sending test data! random: ' + random);
client.connection.send( (new Array(random)).join('TestData') );
}
}, random);
}
}
function flake(i) {
var client = deviceList[i];
var timeBeforeDisconnect = Math.round(Math.random() * 2000);
client._flakeTimeout = setTimeout( function() {
disconnect(i);
}, timeBeforeDisconnect);
}
The logs with only normal clients:
$ node --expose_gc memoryleak-server.js
Wed Sep 07 2016 01:23:41 GMT+0900 (JST) Server is listening on port 8080 (ws)
22 MB // initial rss size
21 MB // node memoryleak-client-normal.js 100
35 MB
40 MB
45 MB
48 MB
50 MB
56 MB
58 MB
57 MB
57 MB
59 MB
59 MB
59 MB
59 MB
60 MB
60 MB
60 MB
58 MB
59 MB
59 MB
58 MB
59 MB
The logs with single buggy client and normal clients:
$ node --expose_gc memoryleak-server.js
Wed Sep 07 2016 01:26:28 GMT+0900 (JST) Server is listening on port 8080 (ws)
22 MB // initial rss size
21 MB // node memoryleak-client-normal.js 100
36 MB // node memoryleak-client-buggy.js
98 MB
145 MB
195 MB
242 MB
292 MB
332 MB
332 MB
559 MB // memoryleak-client-buggy.js exited
366 MB
280 MB
182 MB
182 MB
181 MB
182 MB
182 MB
182 MB
180 MB
172 MB
172 MB
173 MB
172 MB
172 MB
172 MB
The rss of server will not return to a low level value. And memoryleak-client-buggy.js took > 1GB memory when running.
Any news on this?