diff --git a/ADVANCED_README.md b/ADVANCED_README.md index 260facb964..002a112a9e 100644 --- a/ADVANCED_README.md +++ b/ADVANCED_README.md @@ -379,7 +379,7 @@ $ pm2 start app.js -i 3 ### Considerations -- You don't need to modify anything from you code to be able to use this nifty feature. +- You don't need to modify anything from your code to be able to use this nifty feature. - In your application the environment variable `NODE_APP_INSTANCE` is exposed so you can listen for different port if needed. (e.g .listen(8000 + process.env.NODE_APP_INSTANCE)) - Be sure your **application is stateless** meaning that there is not any local data stored in the process, like sessions/websocket connections etc. Use Redis, Mongo or other DB to share states between processes diff --git a/bin/pm2 b/bin/pm2 index efc3389239..721b9ab9cc 100755 --- a/bin/pm2 +++ b/bin/pm2 @@ -22,6 +22,7 @@ CLI.pm2Init(); commander.version(pkg.version) .option('-v --version', 'get version') .option('-s --silent', 'hide all messages', false) + .option('-a --auto-gc', '(HIGH LOAD) let PM2 handle the garbage collector for better performance') .option('-m --mini-list', 'display a compacted list without formatting') .option('-f --force', 'force actions') .option('-n --name ', 'set a for script') diff --git a/lib/God/ClusterMode.js b/lib/God/ClusterMode.js index 55f8f5f95e..5ff3d8ef68 100644 --- a/lib/God/ClusterMode.js +++ b/lib/God/ClusterMode.js @@ -36,6 +36,13 @@ module.exports = function ClusterMode(God) { env_copy.name, env_copy.pm_id); + if (env_copy.auto_gc) { + env_copy.node_args = env_copy.node_args.concat([ + '--expose-gc', + '--nouse-idle-notification' + ]); + } + if (env_copy.node_args && Array.isArray(env_copy.node_args)) { cluster.settings.execArgv = env_copy.node_args; } diff --git a/lib/ProcessContainer.js b/lib/ProcessContainer.js index ad624c76ea..fe832a9c92 100644 --- a/lib/ProcessContainer.js +++ b/lib/ProcessContainer.js @@ -122,6 +122,15 @@ function exec(script, stds) { } }); } + + if (msg.type === 'run:gc') { + if (global.gc) { + try{ + global.gc(); + } catch(e) {} + } + } + }); var moment = null; diff --git a/lib/Worker.js b/lib/Worker.js index e7af11fc07..eaa06ebc7d 100644 --- a/lib/Worker.js +++ b/lib/Worker.js @@ -55,6 +55,18 @@ module.exports = function(God) { } }; + var garbageCollect = function(proc_key, cb) { + var proc = _getProcessById(proc_key.pm2_env.pm_id); + + if (proc.pm2_env.auto_gc && proc.send && typeof(proc.send) === 'function') { + debug('Running GC for process %s:%s', + proc.pm2_env.name, + proc.pm2_env.pm_id); + proc.send({type:'run:gc'}); + } + }; + + var versioningRefresh = function(proc_key, cb) { var proc = _getProcessById(proc_key.pm2_env.pm_id); if (!(proc && @@ -122,6 +134,7 @@ module.exports = function(God) { debug('[PM2][WORKER] Processing proc id:', proc_key.pm2_env.pm_id); + garbageCollect(proc_key); versioningRefresh(proc_key, function() { maxMemoryRestart(proc_key, function() { return next(); diff --git a/lib/schema.json b/lib/schema.json index 9f767be7ed..fa90860087 100644 --- a/lib/schema.json +++ b/lib/schema.json @@ -36,6 +36,9 @@ "port": { "type": "number" }, + "auto_gc" : { + "type" : "boolean" + }, "log_file": { "type": [ "boolean",