Skip to content

Commit

Permalink
expose and run GC for nodejs to avoid memory intensive actions to run…
Browse files Browse the repository at this point in the history
… in memory limit

run garbage collector automatically
  • Loading branch information
jeremiaswerner committed Mar 10, 2017
1 parent f557a82 commit 9eb7fde
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 4 deletions.
2 changes: 1 addition & 1 deletion core/nodejs6Action/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,4 @@ xmlhttprequest@1.8.0 \
yauzl@2.7.0

# See app.js
CMD node app.js
CMD node --expose-gc app.js
2 changes: 1 addition & 1 deletion core/nodejsAction/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ xmlhttprequest@1.7.0 \
yauzl@2.3.1

# See app.js
CMD node app.js
CMD node --expose-gc app.js
11 changes: 9 additions & 2 deletions core/nodejsActionBase/src/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,16 @@ function NodeActionService(config, logger) {
if (status === Status.ready) {
setStatus(Status.running);

return doRun(req).then(function (result) {
setStatus(Status.ready);
var userCodePromise = doRun(req);
var garbageCollectorPromise = new Promise(function (resolve, reject) {
global.gc();
resolve();
}
);

return Promise.all([userCodePromise, garbageCollectorPromise]).then(function (resolvedPromises) {
var result = resolvedPromises[0];
setStatus(Status.ready);
if (typeof result !== "object") {
console.error('Result must be of type object but has type "' + typeof result + '":', result);
return errorMessage(502, "The action did not return a dictionary.");
Expand Down
12 changes: 12 additions & 0 deletions tests/dat/actions/memory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
function eat(memoryMB) {
var bytes = 1*1024*1024*memoryMB;
var buffer = new Buffer.alloc(bytes, 'a');
buffer = null;
console.log('done.');
}

function main(msg) {
console.log('helloEatMemory', 'memory ' + msg.payload + 'MB');
eat(msg.payload);
return {msg: 'OK, buffer of size ' + msg.payload + ' MB has been filled.'};
}
20 changes: 20 additions & 0 deletions tests/src/test/scala/whisk/core/limits/ActionLimitsTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,24 @@ class ActionLimitsTests extends TestHelpers with WskTestHelpers {
}.length shouldBe 1
}
}

it should "be able to run memory intensive actions multiple times by running the GC in the action" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
val name = "TestNodeJsMemoryActionAbleToRunOften"
assetHelper.withCleaner(wsk.action, name, confirmDelete = true) {
val allowedMemory = 512 megabytes
val actionName = TestUtils.getTestActionFilename("memory.js")
(action, _) => action.create(name, Some(actionName), memory = Some(allowedMemory))
}

for( a <- 1 to 10){
val run = wsk.action.invoke(name, Map("payload" -> "128".toJson))
withActivation(wsk.activation, run) { response =>
response.response.status shouldBe "success"
response.response.result shouldBe Some(JsObject(
"msg" -> "OK, buffer of size 128 MB has been filled.".toJson))
}
}
}

}

0 comments on commit 9eb7fde

Please sign in to comment.