2012-11-21 13 views
10

में JSON.stringify आउटपुट को स्ट्रीमिंग/पिपिंग करना मेरे पास एक परिदृश्य है जहां मुझे अपने नोड.जेएस/एक्सप्रेस रीस्टफुल एपीआई से जेएसओएन स्ट्रिंग में परिवर्तित एक बहुत बड़ी वस्तु वापस करने की आवश्यकता है।नोड.जेएस/एक्सप्रेस

res.end(JSON.stringify(obj)); 

हालांकि, यह अच्छी तरह से स्केल नहीं दिखता है। विशेष रूप से, यह 1-2 परीक्षणों के साथ मेरी परीक्षण मशीन पर बहुत अच्छा काम करता है, लेकिन मुझे संदेह है कि यह ऑपरेशन CPU & मेमोरी उपयोग को मार सकता है जब कई क्लाइंट बड़े JSON ऑब्जेक्ट्स को एक साथ अनुरोध कर रहे हैं।

मैंने एसिंक जेएसओएन लाइब्रेरी की तलाश में चारों ओर पोक किया है, लेकिन the only one I found में कोई समस्या है (विशेष रूप से, मुझे एक [रेंज एरर] मिलता है)। इतना ही नहीं, लेकिन यह एक बड़े हिस्से में स्ट्रिंग देता है (उदाहरण के लिए, कॉलबैक को पूरी स्ट्रिंग के साथ एक बार बुलाया जाता है, जिसका अर्थ है कि स्मृति पदचिह्न कम नहीं होता है)।

जो मैं वास्तव में चाहता हूं वह JSON.stringify फ़ंक्शन का एक पूरी तरह से असीमित पाइपिंग/स्ट्रीमिंग संस्करण है, जैसे कि यह डेटा लिखता है क्योंकि यह सीधे स्ट्रीम में पैक होता है ... इस प्रकार मुझे स्मृति पदचिह्न दोनों से बचाता है, और इससे भी एक तुल्यकालिक फैशन में सीपीयू का उपभोग।

+0

आप एक स्ट्रीम बनाने, भाप में स्ट्रिंग के रूप में वस्तु लिखते हैं, और अंत में सिर्फ पाइप के लिए धारा रेस। – wayne

उत्तर

9

आदर्श रूप से, आपको अपने डेटा को स्ट्रीम करना चाहिए क्योंकि आपके पास यह है और सब कुछ एक बड़ी वस्तु में बफर नहीं करना चाहिए। यदि आप इसे बदल नहीं सकते हैं, तो आपको छोटी इकाइयों में स्ट्रिंग को तोड़ने की आवश्यकता है और setImmediate का उपयोग करके अन्य ईवेंट को संसाधित करने के लिए मुख्य ईवेंट लूप को अनुमति दें। उदाहरण कोड (मैं मुख्य उद्देश्य शीर्ष स्तर गुण के बहुत सारे है मान लेते हैं और काम को विभाजित करने के लिए उन्हें इस्तेमाल करेंगे):

function sendObject(obj, stream) { 
    var keys = Object.keys(obj); 
    function sendSubObj() { 
     setImmediate(function(){ 
      var key = keys.shift(); 
      stream.write('"' + key + '":' + JSON.stringify(obj[key])); 
      if (keys.length > 0) { 
      stream.write(','); 
      sendSubObj(); 
      } else { 
      stream.write('}'); 
      } 
     }); 
    }) 
    stream.write('{'); 
    sendSubObj(); 
} 
+0

अच्छा कार्यान्वयन, धन्यवाद! –

+0

अच्छा, लेकिन क्या यह ओबीजे के शीर्ष स्तर से मुख्य नाम और ऑब्जेक्ट विवरण को छोड़ नहीं देता है? – Paul

+0

हां, आप सही हैं। मैं कोड अपडेट करूंगा –

5

ऐसा लगता है जैसे आप डोमिनिक टैर के JSONStream चाहते हैं। जाहिर है, एक्सप्रेस के साथ इसे मर्ज करने के लिए कुछ असेंबली की आवश्यकता है।

हालांकि, यदि आप सीपीयू को अधिकतम (स्ट्रिंगिफ़) ऑब्जेक्ट करने का प्रयास कर रहे हैं, तो उस वस्तु को टुकड़ों में विभाजित करने से समस्या वास्तव में हल नहीं हो सकती है। स्ट्रीमिंग मेमोरी पदचिह्न को कम कर सकती है, लेकिन आवश्यक "काम" की कुल मात्रा को कम नहीं करेगी।

+0

यह काम की कुल मात्रा को कम नहीं कर सकता है, लेकिन समय के साथ इसे वितरित कर रहा है (process.nextTick के माध्यम से अलग करना) का मतलब है कि सीपीयू pegged नहीं मिलेगा। –

+2

नोट: process.next अब ईवेंट लूप पर पहुंचने से पहले निष्पादित करें। 'SetImmediate' का प्रयोग करें। – CoolAJ86

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

  • कोई संबंधित समस्या नहीं^_^