Javascript 如何使用Node 6.2.1处理长循环上的内存消耗

Javascript 如何使用Node 6.2.1处理长循环上的内存消耗,javascript,node.js,memory-leaks,garbage-collection,bluebird,Javascript,Node.js,Memory Leaks,Garbage Collection,Bluebird,我一直在尝试实现一个作业,该作业将运行数据库中的数百万个条目,以根据另一个集合中的值更新属性 结构是沿着 const Promise = require('bluebird'); var updateFunc = Promise.coroutine(function* (skip, limit) { let objects = yield repository.getDocs({}, skip, limit); // perform other actions on objec

我一直在尝试实现一个作业,该作业将运行数据库中的数百万个条目,以根据另一个集合中的值更新属性

结构是沿着

const Promise = require('bluebird');

var updateFunc = Promise.coroutine(function* (skip, limit) {
    let objects = yield repository.getDocs({}, skip, limit);
    // perform other actions on objects
});

var loopFunc = Promise.coroutine(function* () {
    const count = yield repository.countDocs({});

    var skip = 0;
    var limit = 10000;
    let runs = Math.ceil(count/limit);

    for (let i = 0; i < runs; i++) {
        yield updateFunc(skip, limit);
        skip += limit;
    }
});

Promise.coroutine(function* () {
    var start = new Date().getTime();

    yield loopFunc();

    var end = new Date().getTime();
    var timeTaken = ((end - start) / 1000);
    console.log('finished in %s seconds..', parseFloat(timeTaken).toFixed(2));
    process.exit(0);
})();
const Promise=require('bluebird');
var updateFunc=Promise.coroutine(函数*(跳过,限制){
let objects=yield repository.getDocs({},skip,limit);
//对对象执行其他操作
});
var loopFunc=Promise.coroutine(函数*(){
const count=yield repository.countDocs({});
var-skip=0;
风险价值限额=10000;
let runs=Math.ceil(计数/限制);
for(设i=0;i
这会很快消耗内存,直到崩溃

如果我在loopFunc返回后直接将while true移到main函数中,那么大约30秒后它将释放内存

我认为loopFunc会在内存运行时停止释放内存,对于这个作业,我需要一个相当长的运行循环

一个想法是将其分解成若干部分,并在一个单独的子进程中运行每个部分,但我想理解为什么这不起作用

我尝试过的一切都失败了

我认为可能是存储库中的某个东西泄漏了内存,但如果我只是在updateFunc中创建一个巨大的数组,而没有引用任何其他内容,它仍然保留内存

我还尝试使用--expose gc on start和global.gc()强制垃圾收集,每次循环中运行一次,这也无法产生更好的结果

你知道我在这里遗漏了什么吗

*更新*

我已经设法使用process.nextTick而不是循环来控制内存

我的新代码看起来像

const Promise = require('bluebird');
var kill = false;

var updateFunc = Promise.coroutine(function* (skip, limit, runs, run, count) {
    let objects = yield repository.getDocs({}, skip, limit);
    // perform other actions on objects

    if (run < runs) {
        process.nextTick(Promise.coroutine(function* () {
            yield locator.helper.makePromise(null, 2000, true);
            yield updateFunc(skip+limit, limit, runs, run+1, count);
        }));
    } else {
        kill = true;
    }
});

Promise.coroutine(function* () {
    var start = new Date().getTime();

    var count = yield locator.repository.count(locator.db.absence, {});
    console.log('checking %s companies...', count);

    var skip = 0;
    var limit = 10000;
    let runs = Math.ceil(count/limit);

    yield updateFunc(skip, limit, runs+1, 1, count);

    while(!kill) {
        yield locator.helper.makePromise(null, 5000, true);
    }

    var end = new Date().getTime();
    var timeTaken = ((end - start) / 1000);
    console.log('finished in %s seconds..', parseFloat(timeTaken).toFixed(2));
    process.exit(0);
})();
const Promise=require('bluebird');
var kill=false;
var updateFunc=Promise.coroutine(函数*(跳过、限制、运行、运行、计数){
let objects=yield repository.getDocs({},skip,limit);
//对对象执行其他操作
如果(运行<运行){
process.nextTick(Promise.coroutine)(函数*(){
yield locator.helper.makePromise(null,2000,true);
收益率更新函数(跳过+限制,限制,运行,运行+1,计数);
}));
}否则{
kill=true;
}
});
Promise.coroutine(函数*(){
var start=new Date().getTime();
var count=yield locator.repository.count(locator.db.idence,{});
console.log('正在检查%s个公司…',计数);
var-skip=0;
风险价值限额=10000;
let runs=Math.ceil(计数/限制);
收益率更新函数(跳过、限制、运行+1、1、计数);
而(!杀死){
yield locator.helper.makePromise(null,5000,true);
}
var end=new Date().getTime();
var时间=((结束-开始)/1000);
console.log('在%s秒内完成..',parseFloat(耗时).toFixed(2));
进程退出(0);
})();
使用nextTick调用updateFunc似乎允许GC完成它的工作,这很好。内存增长很快,当它达到大约1GB时,就会被清理掉

我需要带有等待的while循环,以便updateFunc有时间运行到完成,一旦达到最大运行次数,我就可以中断并终止进程

我仍然在寻找改进的方法,但我终于取得了进步