简体   繁体   English

如何处理大对象并避免出现内存不足错误?

[英]How can I handle large objects and avoid an out of memory error?

I'm trying to handle a large array, but the object is sometimes so large that it breaks the server with: 我正在尝试处理一个大数组,但是该对象有时太大,以致于破坏了服务器:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory

I can reproduce this locally by doing node --max-old-space-size=100 and then running my process. 通过执行node --max-old-space-size=100 ,然后运行我的进程,可以在本地重现此代码。 Without setting this option it works fine. 如果不设置此选项,它将正常工作。

Here's the section of the code where it's breaking 这是代码中断的部分

function setManagers(json){
return Q.all(json.map(function(obj){
    return getUserByUsername(obj.username)
    .then(function(user){
        console.log('got here'); //never hits
        ...

function getUserByUsername(username){
    console.log('getting user'); //hits
    return UserModel.findOneQ({username:username})
    .then(function(user){
        console.log('search finished'); //never hits
        if(user){
            console.log('got user');
            return Q(user);
        }else{
            console.log('no user');
            return Q.reject({message:'user ' + username + ' could not be found locally'});
        }
    });
}

I think that this problem is due to it being a huge array, which has a length of over 5000 我认为这个问题是由于它是一个巨大的数组,长度超过5000

If I were to remove the option to limit my memory, or use a smaller data set, it'd work. 如果我要删除限制内存的选项,或者使用较小的数据集,则可以使用。

Is there any easy way to avoid this error? 有什么简单的方法可以避免此错误?

The problem is that you're doing too many database calls simultaneously. 问题是您同时进行了太多的数据库调用。

I would change your logic to send to the database a sorted string with all the usernames joined by commas, and I would get all the users needed at once. 我将更改您的逻辑,以将排序后的字符串发送给数据库,其中所有用户名均以逗号开头,这样我将立即获得所有需要的用户。 Then, I would loop through those users and do whatever you're doing with the users you're receiving from the database. 然后,我将遍历这些用户,并对从数据库接收到的用户执行任何操作。


Another solution, that will not be obtrusive to your current logic, is to perform the database operations one by one, using, for example, a promise-while: 另一个解决方案不会对您当前的逻辑造成干扰,例如,使用promise-while来逐个执行数据库操作:

function pwhile(condition, body) {
  var done = Q.defer();

  function loop() {
    if (!condition())
      return done.resolve();
    Q.when(body(), loop, done.reject);
  }

  Q.nextTick(loop);

  return done.promise;
}

function setManagers(json) {
  var i = 0;
  return pwhile(function() { i < json.length; }, function() {
    var p = getUserByUsername(json[i].username);
    i++;
    return p;
  });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM