13101530
为了方便大家看到重点重新编辑了一下
做了一个简单的测试,代码如下:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var UserSchema = new Schema({
name : { type: String, index: true },
pass : { type: String },
email : { type: String },
});
var User = mongoose.model('User', UserSchema);
mongoose.connect('mongodb://127.0.0.1/outmem');
for ( var i = 0; i < 1000000; i++ ) {
user = new User();
user.name = 'outmem';
user.pass = '123456';
user.email = 'outmem[@outmem](/user/outmem).com';
user.save();
console.log(i);
}
或者是加一个:
delete user;
都会出现内存用完的情况,windows和linux截图如下:


不知道什么原因.是还没来得及回收内存还是因为我的代码有问题?
下面是进一步测试的结果:
代码修改如下,把分配和保存放到函数里面,任然一样:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
//
// 为了让效果更快的出现,附加的数据
//
var AppendData = new Schema({
name : { type: String },
pass : { type: String },
email : { type: String },
});
var UserSchema = new Schema({
name : { type: String, index: true },
pass : { type: String },
email : { type: String },
append : [AppendData]
});
var User = mongoose.model('User', UserSchema);
mongoose.connect('mongodb://127.0.0.1/outmem');
var addCount = 0;
function addUser() {
console.log('addUser' + (addCount++));
user = new User();
user.name = 'outmem';
user.pass = '123456';
user.email = 'outmem[@outmem](/user/outmem).com';
for ( var j = 0; j < 1000; j++ ) {
user.append.push({name: 'outmem', pass: '123456', email: 'outmem[@outmem](/user/outmem).com'});
}
user.save(function(err) {
if ( err ) {
console.log('save error');
}
});
}
while ( true ) {
addUser();
}
代码修改如下,通过定时器回调,表现良好:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
//
// 为了让效果更快的出现,附加的数据
//
var AppendData = new Schema({
name : { type: String },
pass : { type: String },
email : { type: String },
});
var UserSchema = new Schema({
name : { type: String, index: true },
pass : { type: String },
email : { type: String },
append : [AppendData]
});
var User = mongoose.model('User', UserSchema);
mongoose.connect('mongodb://127.0.0.1/outmem');
var addCount = 0;
function addUser() {
console.log('addUser' + (addCount++));
user = new User();
user.name = 'outmem';
user.pass = '123456';
user.email = 'outmem[@outmem](/user/outmem).com';
for ( var j = 0; j < 1000; j++ ) {
user.append.push({name: 'outmem', pass: '123456', email: 'outmem[@outmem](/user/outmem).com'});
}
user.save(function(err) {
if ( err ) {
console.log('save error');
}
});
}
setInterval(addUser, 1);
继续修改如下,表现良好:仔细看addUserStub这个函数,如果把里面的数字修改大一点还是会OOM.
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
//
// 为了让效果更快的出现,附加的数据
//
var AppendData = new Schema({
name : { type: String },
pass : { type: String },
email : { type: String },
});
var UserSchema = new Schema({
name : { type: String, index: true },
pass : { type: String },
email : { type: String },
append : [AppendData]
});
var User = mongoose.model('User', UserSchema);
mongoose.connect('mongodb://127.0.0.1/outmem');
var addCount = 0;
function addUser() {
console.log('addUser' + (addCount++));
user = new User();
user.name = 'outmem';
user.pass = '123456';
user.email = 'outmem[@outmem](/user/outmem).com';
for ( var j = 0; j < 1000; j++ ) {
user.append.push({name: 'outmem', pass: '123456', email: 'outmem[@outmem](/user/outmem).com'});
}
user.save(function(err) {
if ( err ) {
console.log('save error');
}
});
}
function addUserStub() {
for ( var i = 0; i < 10; i++ ) { // 这里的值不能过大,过大的话也会出现
addUser();
}
}
setInterval(addUserStub, 1);
这个时候我就在想到底是mongoose的原因还是node的原因?为了排除是mongoose导致的,所以修改代码如下,删除了user.save(),让mongoose不和数据库之间交互,只无限的分配内存,结果出乎意料,表现很良好
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
//
// 为了让效果更快的出现,附加的数据
//
var AppendData = new Schema({
name : { type: String },
pass : { type: String },
email : { type: String },
});
var UserSchema = new Schema({
name : { type: String, index: true },
pass : { type: String },
email : { type: String },
append : [AppendData]
});
var User = mongoose.model('User', UserSchema);
mongoose.connect('mongodb://127.0.0.1/outmem');
var addCount = 0;
function addUser() {
console.log('addUser' + (addCount++));
user = new User();
user.name = 'outmem';
user.pass = '123456';
user.email = 'outmem[@outmem](/user/outmem).com';
for ( var j = 0; j < 10000; j++ ) {
user.append.push({name: 'outmem', pass: '123456', email: 'outmem[@outmem](/user/outmem).com'});
}
}
for ( var i = 0; i < 10000000; i++ ) {
addUser();
}
最开始我以为是node单线程导致的,因为一直循环没有机会执行内存回收,最后这段代码证明不是因为这个原因,node还是没有低级到这个地步的.
通过这些代码,初步猜测,有可能有两个原因:
有可能是因为mongoose缓存了用户操作,当有很多的请求的时候,mongodb处理不过来,缓存的操作占用了很大的内存,并没有来得及释放.这样看的话主要原因在于mongoose缓存操作的问题.
另一可能是mongoose在和mongodb交互的时候占用了大量内存,没来得及释放那么为什么没来得及释放呢?所以也有可能是因为node在调用路径太深的时候,内存回收算法有问题?
我是5月29号才接触node以及相关的东西,所以我的javascript水平很菜,所以暂时只能做一些黑盒测试,恕我不能继续深入分析mongoose的代码了.期待某位同学能够深入一下,不过也有可能是因为我自己写的代码什么地方不对,如果某位同学发现了,留个言解释一下,感激不尽。
感谢 @wenbob 的分析,虽然我不赞成你的结果,但是让我也进一步的测试了.具体测试在下面的回复中.