我的Nodetime堆快照中有一些令人惊讶的结果:
我是否正确地读到我的堆中有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想法吗?
答案 0 :(得分:2)
这一行看起来效率低下:
var user = extend({},User).initialize();
我假设extend
调用会复制User
对象,然后调用其initialize
方法。为什么要在每个API调用上复制User
对象?
然后在initialize
调用中创建一个新的Mongoose架构对象,然后通过api.db.model
调用将其注册为模型。创建一次模式并在初始化期间注册它不是更好吗?
这两者的组合可能导致每次调用创建的对象数量超过必要的数量,我敢打赌那些注册的Mongoose模型不容易GC。