各位大神们,我想这样子封装一个网络连接,但在被拼命发包时进程内存涨到200M左右就崩掉了,是因为闭包的问题,还是Buffer拼接,还是因为一下子收到的数据包太多一次过用for处理,还是其他问题啊~~~ 我是一只小小小小鸟。。。。。。
var net = require('net');
function buildConnection(getPacks, buildPack) {
return function(sock) {
var self = this;
this.buf = new Buffer(0);
sock.on('data', function(data) {
self.buf = Buffer.concat([self.buf, data]);
var packs = getPacks(self);
for (var i = 0; i < packs.length; i++) {
// do something with pack
}
}
}
}
}
var Connection = buildConnection(aGetPacksfunction, aBuildPackfunction);
var server = net.createserver();
server.on('connection', function(sock) {
var conn = new Connection(sock);
});
server.listen(8000);
6 回复
有2个原因吧:
- v8对gc不是很积极,因为gc很昂贵。 v8对小内存对象更不积极,buffer对象是小内存,但是它hold住的数据在v8的heap外,所以会造成内存暴涨,因为buffer释放缓慢 . 你可以使用node xxx --export-gc 然后在程序里定时执行gc()。
- 你在for循环时,低层libuv一直在接收数据 这个是属于proactor模式吧。底层一直在收,你可以通过接口sock.pause() and sock.resume()去控制接收buffer。
参考: https://github.com/clowwindy/shadowsocks-nodejs 的readme,作者目前放弃了nodejs版本就是因为内存的问题
self.buf = Buffer.concat([self.buf, data]);
我很好奇,这样不是每次都在self.buf后append data,self.buf不是会越来越大吗? 除非处理完pack后,重置了self.buf。 但这样tcp上的粘包没办法处理。
这是我的demo:
Session.prototype.append = function(buf) {
if (!buf)
return
if (!this._buf) {
this._buf = buf
this._buf_len = buf.length
return
}
var left = this._buf.length - this._buf_len
if (left>=buf.length) {
buf.copy(this._buf,this._buf_len)
this._buf_len+=buf.length
return
}
this._buf = Buffer.concat([this._buf.slice(0,this._buf_len),buf])
this._buf_len+=buf.length
}