读取Node.js堆快照(通过Nodetime创建) - 为什么我的对象不是GC' d?

时间:2012-10-14 14:56:10

标签: node.js

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

enter image description here

我是否正确地读到我的堆中有1706个“用户”实例?这看起来非常高,我甚至不确定如何分配这么多。在任何情况下,是否有任何提示/技巧/提示,以找出为什么这些悬挂?我已经在我的代码上使用了JSHint来确保没有分配自由全局变量。所有内容都应该包含在请求的封闭范围内......那么为什么在请求完成时不会对用户,帖子等进行垃圾回收?这里有一些(编辑过的)代码来展示我是如何做事的......

非常令人惊讶的是,我在最后一次API调用完成后大约10米处获取了上述堆快照。因此,在触发分配的请求完成后,这些对象都会闲置很久!

代码:

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想法吗?

1 个答案:

答案 0 :(得分:2)

这一行看起来效率低下:

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

我假设extend调用会复制User对象,然后调用其initialize方法。为什么要在每个API调用上复制User对象?

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

这两者的组合可能导致每次调用创建的对象数量超过必要的数量,我敢打赌那些注册的Mongoose模型不容易GC。