【问题标题】:Memory leak - promises in a loop内存泄漏 - 循环中的承诺
【发布时间】:2018-04-28 06:27:51
【问题描述】:

我的节点应用程序的 CPU 使用率正在逐渐增加。我发现内存泄漏正在发生。通过 AppDynamics,我发现在 processImmediate 调用树下有大量保留的内存随着时间的推移不断增加。当我深入研究时,我发现问题出在 settlePromises 函数上。

我想听听你对我一直在使用的 Promise 的一种特殊用法的看法。循环的承诺。以下是此类用法的示例函数结构。

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;
    });
}

一个小时内的堆增长如下图所示

上述函数必须对数据数组中的对象进行同步更新。这样做有内存泄漏的可能性吗?

【问题讨论】:

  • 是的。还有机会是它在您的代码中,而不是在库中。开始削减东西 - 将问题隔离到最小的可重现代码。
  • @c69 感谢您的评论。您在上述用法中看到任何明显的错误吗?也许我会尝试用这个函数做一个测试用例,用 setInterval 运行它并检查堆增长。
  • 带有promises.push / promises.reduce 的部分是明显的代码异味。嵌套的 try..catch 是代码异味。 For..in 是自 2009 年以来没有人使用的东西(原 Crockford 的书)。如果..else 块在 reduce 中是无用的 - 两个分支返回相同的值。
  • @JLRishe 对不起,我的错。现在编辑了。

标签: node.js memory-leaks promise bluebird appdynamics


【解决方案1】:

不确定这是否会导致内存泄漏,但您的函数肯定有大量不必要的垃圾,可以使用 Bluebird 的 Promise.mapSeries() 和其他 Bluebird 助手清理。

这样做很可能有助于减少内存泄漏。

doSomething 函数减少到 8 行:

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

【讨论】:

    猜你喜欢
    • 2022-01-06
    • 2019-02-24
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-08
    • 2019-06-21
    相关资源
    最近更新 更多