Fix a few memory leaks; add /gc console command

3 memory leaks were fixed
  - ipThrottle (due to the periodic cleaner clearing the wrong object...)
  - ipCount (shouldn't have leaked very much, but removing obsolete data is good practice)
  - lastguestlogin (again, shouldn't leak much, but should be cleared periodically anyways)
A new console command (i.e. from the terminal running node) was added: /gc
  - If the process is invoked as node --expose-gc index.js, /gc allows you to manually invoke the garbage collector
This commit is contained in:
calzoneman 2014-04-10 21:54:46 -05:00
parent e973813718
commit 04dbb3444b
8 changed files with 53 additions and 16 deletions

View File

@ -128,3 +128,8 @@ contacts:
- name: 'calzoneman'
title: 'Developer'
email: 'cyzon@cytu.be'
# If set to true, when the ipThrottle and lastguestlogin rate limiters are cleared
# periodically, the garbage collector will be invoked immediately.
# The server must be invoked with node --expose-gc index.js for this to have any effect.
aggressive-gc: false

View File

@ -40,5 +40,12 @@ function handleLine(line) {
if (line === "/reload") {
Logger.syslog.log("Reloading config");
Config.load("config.yaml");
} else if (line === "/gc") {
if (global && global.gc) {
Logger.syslog.log("Running GC");
global.gc();
} else {
Logger.syslog.log("Failed to invoke GC: node started without --expose-gc");
}
}
}

View File

@ -69,17 +69,6 @@ function initPasswordResetCleanup(Server) {
}, CLEAN_INTERVAL);
}
/* Clean out old rate limiters */
function initIpThrottleCleanup(Server) {
setInterval(function () {
for (var ip in Server.ipThrottle) {
if (Server.ipThrottle[ip].lastTime < Date.now() - 60 * 1000) {
delete Server.ipThrottle[ip];
}
}
}, 5 * 60 * 1000);
}
function initChannelDumper(Server) {
var CHANNEL_SAVE_INTERVAL = parseInt(Config.get("channel-save-interval"))
* 60000;
@ -102,7 +91,6 @@ module.exports = function (Server) {
init = Server;
initStats(Server);
initAliasCleanup(Server);
initIpThrottleCleanup(Server);
initChannelDumper(Server);
initPasswordResetCleanup(Server);
};

View File

@ -86,7 +86,8 @@ var defaults = {
title: "Developer",
email: "cyzon@cytu.be"
}
]
],
"aggressive-gc": false
};
/**

View File

@ -12,7 +12,6 @@ var CONNECT_RATE = {
sustained: 0.1
};
// Keep track of rate limiting by IP
var ipThrottle = {};
// Keep track of number of connections per IP
var ipCount = {};
@ -80,6 +79,10 @@ function handleConnection(sock) {
sock.on("disconnect", function () {
ipCount[ip]--;
if (ipCount[ip] === 0) {
/* Clear out unnecessary counters to save memory */
delete ipCount[ip];
}
});
if (!(ip in ipCount)) {
@ -139,3 +142,21 @@ module.exports = {
}
}
};
/* Clean out old rate limiters */
setInterval(function () {
for (var ip in ipThrottle) {
if (ipThrottle[ip].lastTime < Date.now() - 60 * 1000) {
var obj = ipThrottle[ip];
/* Not strictly necessary, but seems to help the GC out a bit */
for (var key in obj) {
delete obj[key];
}
delete ipThrottle[ip];
}
}
if (Config.get("aggressive-gc") && global && global.gc) {
global.gc();
}
}, 5 * 60 * 1000);

View File

@ -9,7 +9,7 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
const VERSION = "3.0.2";
const VERSION = "3.0.3";
var singleton = null;
var Config = require("./config");

View File

@ -604,6 +604,21 @@ User.prototype.guestLogin = function (name) {
});
};
/* Clean out old login throttlers to save memory */
setInterval(function () {
var delay = Config.get("guest-login-delay");
for (var ip in lastguestlogin) {
var diff = (Date.now() - lastguestlogin[ip]) / 1000;
if (diff > delay) {
delete lastguestlogin[ip];
}
}
if (Config.get("aggressive-gc") && global && global.gc) {
global.gc();
}
}, 5 * 60 * 1000);
User.prototype.initUserPLCallbacks = function () {
require("./userplaylists").init(this);
};

View File

@ -2,7 +2,7 @@
"author": "Calvin Montgomery",
"name": "CyTube",
"description": "Online media synchronizer and chat",
"version": "3.0.2",
"version": "3.0.3",
"repository": {
"url": "http://github.com/calzoneman/sync"
},