5

我的 Nodetime 堆快照中有一些令人惊讶的结果:

在此处输入图像描述

我是否正确地阅读了我的堆中有 1706 个“用户”实例?这似乎高得离谱,我什至不太确定我会如何分配这么多。无论如何,是否有任何提示/技巧/提示可以找出这些问题的原因?我已经在我的代码中使用了 JSHint 来确保没有分配空闲的全局变量。一切都应该包含在请求的闭包范围内……那么为什么当请求完成时用户、帖子等不被垃圾收集呢?这是一些(编辑过的)代码来展示我是如何做事的......

非常令人惊讶的是,我在最后一次 API 调用完成后大约 10m 拍摄了上面的堆快照。所以,在触发它们被分配的请求完成后,这些对象都在附近徘徊了很长时间!

代码:

var User = require('./user').User,
    Q = require('q');

// this function is called via express' router, eg when the client visits myapi.com/users/zane
function getUser(req, res, next)
{
   var user = extend({},User).initialize();

   Q.ncall(user.model.find, user.model, {'username': req.arguments[0]})
   .then(function(data){
       res.writeHead(200, {});
       res.end(JSON.stringify(data));
   })
   .fail(next).end();
}

“用户”模块看起来像这样:

exports.User = extend({}, {
    initialize: function() {
        var Schema = api.mongoose.Schema;
        this.schema = new Schema({
            'username': {'type':String, 'index':true}
        });
        this.model = api.db.model('users', this.schema);
    }

    // ... some other helper functions in here
});

根据我上面的快速代码,我希望分配的用户对象的生命周期仅与请求返回的时间一样长。我在这里错过了一些关键的 Node.js GC 想法吗?

4

1 回答 1

2

这条线看起来效率低得令人怀疑:

var user = extend({},User).initialize();

我假设extend调用复制User对象,然后调用它的initialize方法。User为什么要在每次 API 调用时复制对象?

然后在initialize调用中创建一个新的 Mongoose 模式对象,然后通过调用将其注册为模型api.db.model。一次创建模式并在初始化期间注册它不是更好吗?

这两者的结合可能会导致在每次调用时创建的对象多于必要的数量,我敢打赌那些注册的 Mongoose 模型不会轻易 GC。

于 2012-10-14T23:56:13.387 回答