Memory leak - promises in a loop

Viewed 794

My node app's CPU usage is gradually increasing. I have found that memory leaks are happening. Through AppDynamics, I have found that there is a significant amount of retained memory which keeps increasing over time under processImmediate call tree. As I drilled in, I found the problem was with settlePromises function.

App Dynamics screen shot

I want to get your opinion on one particular usage of promises I have been using. Looping of promises. Below is a sample function structure of such usage.

var dataArray = []; //list of jsons
var Promise = require('node-promise').Promise;

function doSomething(){
    try{
        var promises = [];
        //create function promises and push
        for(var i in dataArray){
            var usage = {};
            usage["user"] = dataArray[i].user;
            promises.push((function(ob){
                var log = extend({},ob);
                return executeFunction(log)}).bind(null,usage));
        }

        //loop and execute
        var respArray = [];
        return (promises.reduce(function(previous , current , index , array){
            try{
                return previous.then(function(resp){
                    if(resp != null)
                        respArray.push(resp);
                    if(promises.indexOf(current)==promises.length -1){
                        return current();
                    }
                    else{
                        return current();
                    }
                });
            }catch(ex){
                throw { ex : ex.stack};
            }
        },delay())).then(function(){
            return data;
        });
    }
    catch(ex){
        console.log(ex,ex.stack);
        throw { ex : ex.stack};
    }
}

function logTemplate(log){
    return models.Users.create(log).then(function(resp){
        return resp;
    },function(err){
        return err;
    });
}

The heap growth over an hour is plotted in the below picture

enter image description here

The above function has to perform a synchronous update with the objects in data array. Is there a chance of memory leak with this?

1 Answers

Not sure whether it would be the cause of memory leaks, but your function definitely has a ton of unnecessary cruft that could be cleaned up with Bluebird's Promise.mapSeries() and other Bluebird helpers.

Doing so may very well help cut down on memory leaks.

doSomething function reduced to 8 lines:

function doSomething(){
    return Promise.delay(1000)  // <-- specify time
        .return(dataArray)
        .mapSeries(function (el) {
            return executeFunction({ user: el.user });
        })
        .filter(function (result) { 
            return result !== null; 
        });
}
Related