2016-01-31 7 views
8

यह सिस्टम स्तर अनुकूलन के संबंध में एक वैचारिक क्वेरी है। नोडजेएस दस्तावेज़ीकरण को पढ़कर मेरी समझ यह है कि पाइप धाराओं पर प्रवाह नियंत्रण करने के लिए आसान हैं।क्या .pipe() node.js में एक memcpy निष्पादित करता है?

पृष्ठभूमि: मेरे पास माइक्रोफ़ोन स्ट्रीम आ रही है और मैं समग्र सिस्टम एमआईपीएस को बचाने के लिए एक अतिरिक्त प्रतिलिपि ऑपरेशन से बचना चाहता था। मैं समझता हूं कि ऑडियो स्ट्रीम के लिए यह एमआईपीएस का एक बड़ा सौदा नहीं है, भले ही हुड के नीचे एक मेमकोपी हो, लेकिन मेरे पास 30fps और UHD रिज़ॉल्यूशन पर कैमरे के फ्रेम में स्ट्रीम करने की योजना भी है। 30 एफपीएस पर यूएचडी रिज़ॉल्यूशन पिक्सेल डेटा की कई प्रतियां बनाना बेहद अक्षम है, इसलिए इसके आसपास कुछ सलाह चाहिए।

उदाहरण कोड:

var spawn = require('child_process').spawn 
var PassThrough = require('stream').PassThrough; 

var ps = null; 
//var audioStream = new PassThrough; 
//var infoStream = new PassThrough; 

var start = function() { 
    if(ps == null) { 
     ps = spawn('rec', ['-b', 16, '--endian', 'little', '-c', 1, '-r', 16000, '-e', 'signed-integer', '-t', 'raw', '-']); 
     //ps.stdout.pipe(audioStream); 
     //ps.stderr.pipe(infoStream); 
     exports.audioStream = ps.stdout; 
     exports.infoStream = ps.stderr; 
    } 
}; 

var stop = function() { 
    if(ps) { 
     ps.kill(); 
     ps = null; 
    } 
}; 

//exports.audioStream = audioStream; 
//exports.infoStream = infoStream; 
exports.startCapture = start; 
exports.stopCapture = stop; 

यहाँ प्रश्न हैं:

  1. प्रवाह नियंत्रण प्रदर्शन करने में सक्षम होने के लिए, source.pipe (गंतव्य) के लिए स्रोत स्मृति से एक memcpy प्रदर्शन करता है हुड के नीचे गंतव्य स्मृति या क्या यह गंतव्य में गंतव्य में संदर्भ पारित करेगा?
  2. टिप्पणी कोड में पासथ्रू क्लास इंस्टेंटेशन शामिल है - मैं वर्तमान में पासथ्रू को मेमकोपी का कारण बनता हूं, और इसलिए मैं पूरे सिस्टम में एक मेम्पी ऑपरेशन सहेज रहा हूं क्योंकि मैंने उपरोक्त टिप्पणियों में जोड़ा है?
  3. अगर मुझे प्रक्रिया और स्पॉन्डेड चाइल्ड प्रक्रिया के बीच एक पाइप बनाना था (How to transfer/stream big data from/to child processes in node.js without using the blocking stdio? में दिखाए गए अनुसार child_process.spawn() का उपयोग करके, मुझे लगता है कि निश्चित रूप से memcpy में परिणाम होता है? क्या प्रतिलिपि बनाने के बजाए संदर्भ बनाने के लिए वैसे भी है?
  4. क्या यह व्यवहार ओएस से ओएस तक भिन्न है? मुझे लगता है कि यह ओएस अज्ञेयवादी होना चाहिए, लेकिन वैसे भी यह पूछना चाहिए।

आपकी सहायता के लिए अग्रिम धन्यवाद। यह मेरे वास्तुकला को एक बड़ा सौदा करने में मदद करेगा।

उत्तर

4

कुछ यूआरएल के संदर्भ के लिए: https://github.com/nodejs/node/
https://github.com/nodejs/node/blob/master/src/stream_wrap.cc
https://github.com/nodejs/node/blob/master/src/stream_base.cc
https://github.com/libuv/libuv/blob/v1.x/src/unix/stream.c
https://github.com/libuv/libuv/blob/v1.x/src/win/stream.c

मैं एक जटिल/विशाल इन और कुछ अन्य फ़ाइलों के आधार पर explaination लेखन की कोशिश की लेकिन मैं इस निष्कर्ष यह होगा के लिए आया था आपको मेरा अनुभव/पढ़ने के बारे में सारांश देने के लिए सबसे अच्छा है कि मुझे आंतरिक रूप से काम करता है:

पाइप बस इसे प्रदर्शित करने वाली धाराओं को जोड़ता है जैसे .on("data", …) को .write(…) द्वारा बिना किसी फूले के बुलाया जाता है।

अब हमें जेएस दुनिया को सी ++/सी दुनिया से अलग करने की आवश्यकता है।
जेएस में डेटा से निपटने पर हम बफर का उपयोग करते हैं। https://github.com/nodejs/node/blob/master/src/node_buffer.cc
वे बस इसके साथ काम करने के लिए शीर्ष पर कुछ कैंडी के साथ आवंटित स्मृति का प्रतिनिधित्व करते हैं।

यदि आप किसी प्रक्रिया के stdout को .on("data", …) श्रोता से कनेक्ट करते हैं तो यह आने वाले खंड को जेएस दुनिया के अंदर और उपयोग के लिए एक बफर ऑब्जेक्ट में कॉपी करेगा।
जेएस दुनिया के अंदर आपके पास .pause() इत्यादि जैसी विधियां हैं (जैसा कि आप नोड्स स्टीम एपीआई दस्तावेज में देख सकते हैं) ताकि आने वाली डेटा इसकी संसाधित की तुलना में तेज़ी से बहती है।

किसी प्रक्रिया के stdout को जोड़ने और उदाहरण के लिए पाइप के माध्यम से एक आउटगोइंग टीसीपी पोर्ट के परिणामस्वरूप एक कनेक्शन होगा जो nginx संचालित करता है। यह थीस स्ट्रीम को कनेक्ट करेगा जैसे कि वे आने वाले डेटा को सीधे आउटगोइंग स्ट्रीम पर कॉपी करके एक दूसरे से बात करेंगे।

जैसे ही आप स्ट्रीम को रोकते हैं, नोड आने वाली स्ट्रीम को रोकने में असमर्थ होने पर आंतरिक बफरिंग का उपयोग करेगा।

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

विशाल छवियों को स्थानांतरित करने के लिए मैं उन्हें टुकड़ों में स्थानांतरित करने की सलाह देता हूं या उन्हें सीधे आउटगोइंग पोर्ट पर पाइप करने की सलाह देता हूं।

चंक रास्ता आपको एक साथ कई ग्राहकों को डेटा भेजने की अनुमति देगा और स्मृति पदचिह्न को बहुत कम रखेगा।

पुनश्च आप इस सार पर एक नज़र है कि मैं सिर्फ पाया लेना चाहिए: https://gist.github.com/joyrexus/10026630
यह गहराई में बताते हैं कि कैसे आप धाराओं

साथ बातचीत कर सकते
संबंधित मुद्दे