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有时间运行到完成,一旦达到最大运行次数,我就可以中断并终止进程
我仍然在寻找改进的方法,但我终于取得了进步