Mongoose / Nodejs验证错误处理,内存泄漏问题

时间:2014-11-19 00:39:14

标签: node.js mongoose

我遇到的情况是,当尝试创建mongoose对象时,nodejs似乎在泄漏内存,但由于验证错误而失败。这对我来说似乎很奇怪,我正在寻求社区的帮助来深入了解它。

在我尝试重新创建问题的示例代码中,我有一个非常简单的Mongoose模型,它将其中一个字段验证为非负数。在下面的代码中反复尝试创建无效对象(XVALUE-1),我看到内存永远在增长。但有效的对象(XVALUE+1)可以正常工作,没有任何泄漏。我正在使用process.memoryUsage().heapUsed变量跟踪内存。

如果尝试创建无效对象,如何摆脱内存泄漏?如果我错误地使用猫鼬,我们将非常感谢任何有关改善使用情况的建议。

版本:mongoose - 3.8.x和nodejs - 0.10.x。

以下是我用来重新创建问题的示例代码:

(function() {
  var MAX_ITER_COUNT, MyModel, MyStuff, Schema, XVALUE, addEntry, conn, iterCount, mongoose;

  mongoose = require("mongoose");

  conn = mongoose.createConnection('mongodb://@127.0.0.1:27017/memtest');

  conn.on("error", function(err) {
    return console.error(err);
  });

  Schema = mongoose.Schema;

  MyStuff = new Schema({
    x: {
      type: Number
    }
  });

  XVALUE = -1;

  MyStuff.path("x").validate((function(val) {
    if (val < 0) {
      return false;
    }
    return true;
  }));

  MyModel = conn.model("MyStuff", MyStuff, "stuff");

  iterCount = 0;

  MAX_ITER_COUNT = 100 * 1000;

  addEntry = function() {
    var currentMem, x;
    currentMem = Math.round(process.memoryUsage().heapUsed / 1024 / 1024);
    console.log("" + iterCount + " - memory is: " + currentMem + " MB");
    x = new MyModel({
      x: XVALUE
    });
    return x.save(function(err) {
      if (err) {
        console.log("" + iterCount + " - failed");
      } else {
        console.log("" + iterCount + " - Save successful");
      }
      if (iterCount < MAX_ITER_COUNT) {
        addEntry();
      }
      return iterCount++;
    });
  };

  conn.on("open", addEntry);

}).call(this);

1 个答案:

答案 0 :(得分:2)

发生的事情是,如果文档无效,x.save异步操作立即完成,一旦其父addEntry函数调用完成就调用其回调。这使得垃圾收集无法运行,内存使用量也在不断增长。

要解决此问题,请在对setImmediate的调用中添加递归addEntry调用,以便GC有机会在迭代之间运行:

addEntry = function() {
  var currentMem, x;
  currentMem = Math.round(process.memoryUsage().heapUsed / 1024 / 1024);
  console.log("" + iterCount + " - memory is: " + currentMem + " MB");
  x = new MyModel({
    x: XVALUE
  });
  return x.save(function(err) {
    if (err) {
      console.log("" + iterCount + " - failed");
    } else {
      console.log("" + iterCount + " - Save successful");
    }
    if (iterCount < MAX_ITER_COUNT) {
      setImmediate(addEntry);
    }
    return iterCount++;
  });
};