如何解码node.js中内存数据的含义并debugging内存泄漏?

我有一个RSS到MongoDB阅读器/刮板​​,通过比我的系统具有内存大的数据集运行。 当我循环数据时,系统变慢。 我相当肯定,这是因为我内存不足。

我已经添加了一些debugging信息,并做了一些更改,但我不知道如何读取debugging输出中给出的信息。

这里是一个debugging输出示例(从致命之前):

100 items Memory: { rss: 11104256, // what is RSS? vsize: 57507840, // what is VSIZE? heapTotal: 4732352, // heapTotal? heapUsed: 3407624 } // heapUsed? 200 items Memory: { rss: 12533760, vsize: 57880576, heapTotal: 6136320, heapUsed: 3541984 } // what key numbers do I watch for? // when do I reach 'situation critical'? // how do I free up memory to prevent problems? 

另外,如果它有帮助和更好的说明,我已经包含了一个代码示例。 我已经做出的一个改变是将所有的需求语句移到GrabRss函数之外。

 var http = require('http'); var sys = require('sys'); var xml2js = require('xml2js'); var util = require('util'); var Db = require('../lib/mongodb').Db, Conn = require('../lib/mongodb').Connection, Server = require('../lib/mongodb').Server, // BSON = require('../lib/mongodb').BSONPure; BSON = require('../lib/mongodb').BSONNative; GrabRss = function(grab, start) { var options = { host: 'www.example.com', port: 80, path: '/rss/'+grab+'/'+start }; var data; var items; var checked = 0; var len = 0; GotResponse = function(res) { var ResponseBody = ""; res.on('data', DoChunk); res.on('end', EndResponse); function DoChunk(chunk){ ResponseBody += chunk; } function EndResponse() { //console.log(ResponseBody); var parser = new xml2js.Parser(); parser.addListener('end', GotRSSObject); parser.parseString(ResponseBody); } } GotError = function(e) { console.log("Got error: " + e.message); } GotRSSObject = function(r){ items = r.item; //console.log(sys.inspect(r)); var db = new Db('rss', new Server('localhost', 27017, {}), {native_parser:false}); db.open(function(err, db){ db.collection('items', function(err, col) { len = items.length; if (len === 0) { process.exit(0); } for (i in items) { SaveItem(item[i], col); } }); }); } SaveMovie = function(i, c) { c.update({'id': i.id}, {$set: i}, {upsert: true, safe: true}, function(err){ if (err) console.warn(err.message); if (++checked >= len) { if (checked < 5000) { delete data; // added since asking delete items; // added since asking console.log(start+checked); console.log('Memory: '+util.inspect(process.memoryUsage())); GrabRss(50, start+checked); } else { console.log(len); process.exit(0); } } else if (checked % 10 == 0) { console.log(start+checked); } }); } http.get(options, GotResponse).on('error', GotError); } GrabRss(50, 0); 

读完这段代码之后,我确实看到GotRSSObject中的items被声明为全局的,因为没有var前缀。

除此之外,我没有看到其他明显的内存泄漏。 一个好的基本技巧是添加一些更多的打印语句来查看内存分配的位置,然后通过声明variables== null来检查您希望清理内存的位置。

与node.js和v8的内存问题是,它不能保证在任何时候垃圾收集和afaik,你不能强制垃圾收集发生。 您将需要限制您正在使用的数据量,以便轻松适应内存,并提供一些error handling(可能使用setTimeout或process.nextTick),直到内存清理完毕。

nextTick的一个build议 – 这是一个非常非常快的电话。 众所周知,Node.js在事件循环上是单线程的。 使用nextTick将在下一个循环中真正执行该函数 – 确保不经常调用它,否则会发现自己正在浪费周期。

关于rssvsizeheapTotalheapUsedvsize是您的进程正在使用的内存的整个大小, rss是实际物理内存中的多less,而不是交换。 heaptotalheapUsed是指您无法控制的v8底层存储。 你将主要关心vsize ,但是你也可以通过OS X上的top Monitor或者Activity Monitor获得更详细的信息(任何人都知道* nix系统上的stream程可视化工具是好的)。