2016-08-27 6 views
0
exports.updateFullCentralRecordSheet = function (req, _id, type) { 
    FullCentralRecordSheet.remove({_ExternalParty: _id, centralRecordType: type, centralSheetType: "Central Sheet"}, function (err) { 
    if (err) { 
     saveErrorLog(req, err); 
    } 
    let query = {"structure.externalPartyRelationships": {$elemMatch: {_ExternalParty: _id}}, disabled: {$mod: [2, 0]}, initialized: true, profitLossType: type}; 
    let fullCentralRecordSheetObjects = []; 
    ProfitLossSheet.find(query).sort({profitLossDate: 1}).lean().exec(function (err, profitLossSheetObjects) { 
     if (err) { 
     saveErrorLog(req, err); 
     } 
     async.each(profitLossSheetObjects, function (profitLossSheetObject, callback) { 
      /// HEAVY COMPUTATION HERE 
      callback(); 
     }); 
     }, function (err) { 
     if (err) { 
      saveErrorLog(req, err); 
     } else { 
      query = {centralRecordMode: {$in: ["Payment In", "Payment Out", "Transfer", "General Out"]}, disabled: {$mod: [2, 0]}, centralRecordType: {$in: ["Split", type]}, _ExternalParty: _id, status: {$ne: "Reject"}}; 
      CentralRecordSheet.find(query).lean().exec(function (err, centralRecordSheetObjects) { 
      if (err) { 
       saveErrorLog(req, err); 
      } 
      _.each(centralRecordSheetObjects, function (centralRecordSheetObject) { 
       // SOME MORE PROCESSING 
      }); 
      fullCentralRecordSheetObjects = _.sortBy(fullCentralRecordSheetObjects, function (fullCentralRecordSheetObject) { 
       return new Date(fullCentralRecordSheetObject.centralRecordDate).getTime(); 
      }); 
      let runningBalance = 0; 
      _.each(fullCentralRecordSheetObjects, function (fullCentralRecordSheetObject) { 
       runningBalance = runningBalance - fullCentralRecordSheetObject.paymentIn.total + fullCentralRecordSheetObject.paymentOut.total + fullCentralRecordSheetObject.moneyIn.total - fullCentralRecordSheetObject.moneyOut.total + fullCentralRecordSheetObject.transferIn.total - fullCentralRecordSheetObject.transferOut.total; 
       fullCentralRecordSheetObject.balance = runningBalance; 
       const newFullCentralSheetRecordObject = new FullCentralRecordSheet(fullCentralRecordSheetObject); 
       newFullCentralSheetRecordObject.save(); // Asynchronous save 
      }); 
      }); 
     } 
     }); 
    }); 
    }); 
}; 

일부 데이터를 처리하여 데이터베이스에 저장하는 코드입니다. 알 수 있듯이 일부 비동기 루프마다 계산이 포함되며 루프 이후에는 최종 데이터 처리가 있습니다. 한 번에 하나의 _id를 전달하면 잘 작동합니다. 그러나이 작업을하려고 할 때NodeJS 비동기 함수를 사용한 for 루프를 사용하는 메모리가 부족합니다.

exports.refreshFullCentralRecordSheetObjects = function (req, next) { 
     ExternalParty.find().exec(function (err, externalPartyObjects) { 
     if (err) { 
      utils.saveErrorLog(req, err); 
      return next(err, null, [req.__(err.message)], []); 
     } 
     _.each(externalPartyObjects, function (externalPartyObject) { 
      updateFullCentralRecordSheet(req, externalPartyObject._id, "Malay"); 
      updateFullCentralRecordSheet(req, externalPartyObject._id, "Thai"); 
     }) 
     return next(err, null, ["Ddd"], ["Ddd"]); 
     }); 
    }; 

나는 루프 할 대상이 약 273 개 있습니다. 이로 인해 메모리 치명적 오류가 발생합니다. 나는 --max-old-space-size=16000을 늘리려고했지만 여전히 충돌하고 있습니다. 나는 task manager를 사용하여 node.exe 프로세스의 메모리를 추적하고 8GB 이상이됩니다.

메모리를 16GB로 늘리는 것이 도움이되지 않는 이유는 확실하지 않지만, 작업 관리자에 따르면 여전히 약 8GB가 충돌합니다. 또 다른 것은 273 개가 아닌 10 개의 레코드 만 처리하려고 할 때 약 500 MB를 사용하는 작업 관리자 보고서입니다. 이 500MB는 서버에 다른 요청을하지 않으면 사라지지 않습니다. 왜 NodeJS 쓰레기 수집 후 10 레코드를 처리 할 수 ​​없기 때문에이 매우 이상한 찾으십시오? 10 개의 레코드가 성공적으로 처리되어 데이터베이스에 저장되었지만 메모리 사용량은 작업 관리자에서 변경되지 않았습니다.

async.forEachLimit을 사용하여 내 업데이트 기능을 비동기로 돌리려고 시도했지만 process.nextTick()으로 재생했지만 여전히 치명적인 오류 메모리 문제가 있습니다. 이 프로그램이 실행되도록하려면 어떻게해야합니까?

+0

'async.each (profitLossSheetObjects, ...'?) 대신에 async.eachLimit (profitLossSheetObjects, ...'를 사용 해보려고 했습니까? – cartant

+0

예 모두 했어요! – Zanko

답변

0

273 대신 10 개의 레코드 만 처리하려고하면 작업 관리자 보고서에 약 500MB가 사용되는 것으로보고됩니다. 이 500MB는 서버에 또 다른 요청을하지 않으면 가 사라지지 않습니다. 나는 이것을 처리 한 후 처리가 끝난 후 왜 NodeJS 가비지 수집을하지 않으므로 이 매우 이상하다고 생각하십니까? 그 10 개의 레코드는 을 성공적으로 처리했지만 데이터베이스에 저장되었지만 메모리 사용량은 작업 관리자에서 변경되지 않습니다.

노드 GC는 게으름입니다 (GC는 동기 작업이므로 루프를 차단하므로 좋은 방법입니다).

쿼리를 페이지 매김하려고합니까?

관련 문제