2011-05-29 18 views
7

मुझे एक आरएसएस मिला है जो मोंगोडीबी रीडर/स्क्रैपर है जो मेरे सिस्टम की तुलना में बड़े डेटा सेट के माध्यम से चलता है। जैसे-जैसे मैं डेटा के माध्यम से लूप करता हूं, सिस्टम धीमा हो जाता है। मुझे यकीन है कि यह कारण है कि मैं स्मृति से बाहर चला रहा हूं।मैं node.js में मेमोरी डेटा के अर्थ को कैसे डीकोड कर सकता हूं और मेमोरी लीक डीबग कर सकता हूं?

मैंने कुछ डीबग जानकारी जोड़ दी है और कुछ बदलाव किए हैं, लेकिन मुझे नहीं पता कि डीबग आउटपुट में दी गई जानकारी को कैसे पढ़ा जाए। , इसके अलावा

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); 

उत्तर

8

इस कोड के माध्यम से पढ़ने के बाद, मैं देख पा रहे हैं कि GotRSSObject में items एक वैश्विक रूप में घोषित किया जाता है, क्योंकि वहाँ कोई var यह prefacing।

इसके अलावा, मुझे कोई अन्य स्पष्ट स्मृति रिसाव दिखाई नहीं देता है। एक अच्छी बुनियादी तकनीक यह देखने के लिए कुछ और प्रिंट स्टेटमेंट जोड़ना है कि स्मृति कहां आवंटित की जा रही है और फिर यह जांचने के लिए कि आप कहां से मेमोरी को साफ़ कर सकते हैं, यह कहकर कि वेरिएबल्स == नल।

node.js और v8 के साथ स्मृति के साथ समस्या यह है कि किसी भी समय और afaik में कचरा इकट्ठा होने की गारंटी नहीं है, आप कचरा संग्रह होने के लिए मजबूर नहीं कर सकते हैं। आप मेमोरी के भीतर आसानी से फिट करने के लिए जिस डेटा को आप काम कर रहे हैं उसे सीमित करना चाहते हैं और मेमोरी साफ़ होने तक प्रतीक्षा करने के लिए कुछ त्रुटि हैंडलिंग (शायद सेटटाइमआउट या process.nextTick के साथ) प्रदान करना चाहते हैं।

अगलीटिक के साथ सलाह का एक शब्द - यह एक बहुत ही तेज कॉल है। Node.js एक इवेंट लूप पर सिंगल थ्रेडेड है क्योंकि हर कोई जानता है। अगलीटिक का उपयोग करने से सचमुच उस फंक्शन को अगले लूप पर निष्पादित कर दिया जाएगा - सुनिश्चित करें कि आप इसे अक्सर कॉल नहीं करते हैं अन्यथा आप स्वयं को चक्रों को बर्बाद कर पाएंगे।

और के बारे में rss, vsize, heapTotal, heapUsed ... vsize स्मृति है कि आपके प्रक्रिया का उपयोग कर रहा है और rss है कैसे इस बात का ज्यादा वास्तविक भौतिक रैम में है और स्वैप नहीं की पूरी आकार है। heaptotal और heapUsed v8 के अंतर्निहित भंडारण का संदर्भ लें जिसका आपके पास कोई नियंत्रण नहीं है। आप अधिकतर vsize से चिंतित होंगे, लेकिन आप top या ओएस एक्स पर गतिविधि मॉनीटर के साथ अधिक विस्तृत जानकारी प्राप्त कर सकते हैं (किसी को * निक्स सिस्टम पर अच्छी प्रक्रिया विज़ुअलाइज़ेशन टूल के बारे में पता है?)।

+0

धन्यवाद। लगता है कि अगला टिक वास्तव में प्रसंस्करण को सुस्त कर दिया है। कोई विचार क्या स्मृति मान (आरएसएस, बनाम, हेपेटोटल, हेप्यूज्ड) का मतलब है? यहां प्रलेखन http://nodejs.org/docs/v0.4.8/api/all.html#process.memoryUsage विस्तार से नहीं जाता है। –

+0

अगली टिक के साथ सलाह का एक शब्द - यह एक बहुत ही तेज कॉल है। Node.js एक इवेंट लूप पर सिंगल थ्रेडेड है क्योंकि हर कोई जानता है। अगलीटिक का उपयोग करने से सचमुच उस फंक्शन को अगले लूप पर निष्पादित कर दिया जाएगा - सुनिश्चित करें कि आप इसे अक्सर कॉल नहीं करते हैं अन्यथा आप स्वयं को चक्रों को बर्बाद कर पाएंगे। – tjarratt

+0

और आरएसएस, बनाम, हेपेटोटल, हेप्यूज्ड के बारे में ... बनाम स्मृति का पूरा आकार है जो आपकी प्रक्रिया का उपयोग कर रहा है और आरएसएस यह है कि इसमें से कितना वास्तविक भौतिक RAM में है और स्वैप नहीं है। Teaptotal और heapused v8 के अंतर्निहित भंडारण का संदर्भ है जिसका आपके पास कोई नियंत्रण नहीं है। – tjarratt

संबंधित मुद्दे

 संबंधित मुद्दे