जब यह अभी भी आंतरिक रूप से थ्रेड्स पर निर्भर करता है, तो Node.js स्वाभाविक रूप से कैसे तेज होता है?


281

मैंने बस निम्नलिखित वीडियो देखा: Node.js का परिचय और अभी भी यह नहीं समझ पाया कि आपको गति के लाभ कैसे मिलते हैं।

मुख्य रूप से, एक बिंदु पर रेयान डाहल (Node.js के निर्माता) का कहना है कि Node.js थ्रेड-आधारित के बजाय इवेंट-लूप आधारित है। धागे महंगे हैं और केवल समवर्ती प्रोग्रामिंग के विशेषज्ञों के उपयोग के लिए छोड़ दिया जाना चाहिए।

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

जो मुझे समझ नहीं आ रहा है वह यह है कि Node.js अभी भी थ्रेड्स का उपयोग कर रहा है ... यह सिर्फ कार्यान्वयन को छिपा रहा है इसलिए यह कैसे तेज़ है यदि 50 लोग 50 फ़ाइलों (वर्तमान में मेमोरी में नहीं) का अनुरोध करते हैं तो अच्छी तरह से 50 थ्रेड आवश्यक नहीं हैं ?

एकमात्र अंतर यह है कि चूंकि इसे आंतरिक रूप से प्रबंधित किया जाता है Node.js डेवलपर को थ्रेडेड विवरणों को कोड करने की आवश्यकता नहीं होती है, लेकिन इसके बाद भी यह थ्रेड्स का उपयोग करके IO (अवरुद्ध) फ़ाइल अनुरोधों को संसाधित करता है।

तो क्या आप वास्तव में सिर्फ एक समस्या (थ्रेडिंग) नहीं ले रहे हैं और इसे छिपा रहे हैं जबकि यह समस्या अभी भी मौजूद है: मुख्य रूप से कई थ्रेड्स, संदर्भ स्विचिंग, डेड-लॉक ... आदि?

कुछ विस्तार होना चाहिए जो मुझे अभी भी समझ में नहीं आया है।


14
मैं आपसे सहमत होने के लिए इच्छुक हूं कि दावा कुछ हद तक सरल है। मेरा मानना ​​है कि नोड का प्रदर्शन लाभ दो चीजों के लिए उबलता है: 1) वास्तविक धागे सभी काफी निम्न स्तर पर निहित हैं, और इस प्रकार आकार और संख्या में विवश रहते हैं, और इस प्रकार थ्रेड सिंक्रोनाइज़ेशन सरल हो जाता है; 2) ओएस-स्तर "स्विचिंग" select()थ्रेड संदर्भ स्वैप की तुलना में तेज है।
पॉइंटी

कृपया यह देखने stackoverflow.com/questions/24796334/...
veritas

जवाबों:


140

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

उनके द्वारा दिए गए उदाहरणों में से एक के बारे में सोचें, जहां एक अनुरोध आता है और आप कुछ क्वेरी चलाते हैं, और फिर उसके परिणामों के साथ कुछ करते हैं। यदि आप इसे मानक प्रक्रियात्मक तरीके से लिखते हैं, तो कोड इस तरह दिख सकता है:

result = query( "select smurfs from some_mushroom" );
// twiddle fingers
go_do_something_with_result( result );

यदि आप उपरोक्त कोड को चलाने वाले एक नए थ्रेड को बनाने के लिए आने वाले अनुरोध को देखते हैं, तो आपको थ्रेड बैठे हुए, कुछ भी नहीं करते हुए query()चल रहा है। (रेयान के अनुसार, अपाचे, मूल अनुरोध को पूरा करने के लिए एक ही धागे का उपयोग कर रहा है, जबकि नेग्नेक्स उन मामलों में इसे बेहतर बना रहा है, क्योंकि वह बात नहीं कर रहा है।)

अब, यदि आप वास्तव में चतुर थे, तो आप ऊपर दिए गए कोड को इस तरह से व्यक्त करेंगे जहां पर्यावरण बंद हो सकता है और जब आप प्रवेश कर रहे हों तो कुछ और कर सकते हैं:

query( statement: "select smurfs from some_mushroom", callback: go_do_something_with_result() );

यह मूल रूप से नोड.जेएस क्या कर रहा है। आप मूल रूप से सजा रहे हैं - एक तरह से जो भाषा और पर्यावरण के कारण सुविधाजनक है, इसलिए क्लोजर के बारे में अंक - आपका कोड इस तरह से है कि पर्यावरण क्या चलता है, और कब के बारे में चतुर हो सकता है। इस तरह से, नोड.जेएस नहीं है इस मायने में नया है कि उसने एसिंक्रोनस आई / ओ का आविष्कार किया (ऐसा नहीं है कि किसी ने भी इस तरह का दावा किया है), लेकिन यह नया है कि जिस तरह से व्यक्त किया गया है वह थोड़ा अलग है।

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


6
ठीक है, मैं निश्चित रूप से देख सकता हूं कि यह प्रदर्शन कैसे बढ़ा सकता है क्योंकि यह मुझे लगता है कि आप अपने सीपीयू को अधिकतम करने में सक्षम हैं क्योंकि कोई थ्रेड या निष्पादन स्टैक नहीं है बस IO के लौटने के लिए इंतजार कर रहा है ताकि रयान ने जो किया है वह प्रभावी रूप से मिल जाए सभी अंतराल को बंद करने का एक तरीका।
राल्फ कारेवियो

34
हाँ, एक बात मैं कहूँगा कि ऐसा नहीं है कि उसे अंतराल को बंद करने का एक तरीका मिल गया है: यह एक नया पैटर्न नहीं है। यह अलग है कि वह प्रोग्रामर को इस तरह से अपने कार्यक्रम को व्यक्त करने के लिए जावास्क्रिप्ट का उपयोग कर रहा है जो इस तरह की अतुल्यकालिकता के लिए बहुत अधिक सुविधाजनक है। संभवतः एक नाइटपिक विस्तार है, लेकिन अभी भी ...
जिपरिपटन

16
यह भी इंगित करने योग्य है कि बहुत सारे I / O कार्यों के लिए, नोड जो भी कर्नेल-स्तर का async I / O एपि उपलब्ध है उसका उपयोग करता है (epoll, kqueue, / dev / poll, जो भी हो)
पॉल

7
मुझे अभी भी यकीन नहीं है कि मैं इसे पूरी तरह से समझता हूं। यदि हम मानते हैं कि एक वेब अनुरोध के अंदर IO संचालन वे हैं जिन्हें अनुरोध को संसाधित करने में अधिकांश समय लगता है और यदि प्रत्येक IO ऑपरेशन के लिए एक नया धागा बनाया जाता है, तो 50 अनुरोधों के लिए जो बहुत तेजी से उत्तराधिकार में आते हैं, हम करेंगे शायद 50 धागे समानांतर में चल रहे हैं और उनके IO भाग को निष्पादित कर रहे हैं। मानक वेब सर्वर से अंतर यह है कि इसमें पूरे अनुरोध को थ्रेड पर निष्पादित किया जाता है, जबकि नोड.जेएस में इसके आईओ भाग के रूप में, लेकिन यह वह हिस्सा है जो अधिकांश समय ले रहा है और प्रतीक्षा करने के लिए धागा बना रहा है।
फ्लोरिन डुमिट्रेस्कु

13
@SystemParadox कि बाहर इशारा करने के लिए धन्यवाद। मैंने वास्तव में हाल ही में विषय पर कुछ शोध किए हैं और वास्तव में पकड़ यह है कि एसिंक्रोनस I / O, जब कर्नेल स्तर पर ठीक से लागू किया जाता है, तो async I / O संचालन करते समय थ्रेड्स का उपयोग नहीं किया जाता है। इसके बजाय I / O ऑपरेशन शुरू होते ही कॉलिंग थ्रेड जारी किया जाता है और I / O ऑपरेशन समाप्त होने पर कॉलबैक निष्पादित किया जाता है और इसके लिए एक थ्रेड उपलब्ध होता है। तो नोड.जेएस 50 आई / ओ संचालन के साथ 50 समवर्ती अनुरोधों को चला सकता है (लगभग) केवल एक धागे का उपयोग करके समानांतर यदि I / O संचालन के लिए async समर्थन ठीक से लागू किया गया है।
फ्लोरिन डुमिट्रेस्कू

32

ध्यान दें!यह एक पुराना उत्तर है। हालांकि यह अभी भी किसी न किसी रूपरेखा में सच है, पिछले कुछ वर्षों में नोड के तेजी से विकास के कारण कुछ विवरण बदल सकते हैं।

यह धागे का उपयोग कर रहा है क्योंकि:

  1. खुला का O_NONBLOCK विकल्प () फ़ाइलों पर काम नहीं करता
  2. तीसरे पक्ष के पुस्तकालय हैं जो गैर-अवरुद्ध आईओ प्रदान नहीं करते हैं।

गैर-अवरुद्ध IO को नकली करने के लिए, थ्रेड्स neccessary हैं: IO को एक अलग थ्रेड में ब्लॉक करना। यह एक बदसूरत समाधान है और बहुत उपरि का कारण बनता है।

यह हार्डवेयर स्तर पर और भी बदतर है:

  • DMA के साथ CPU अतुल्यकालिक रूप से IO को ऑफलोड करता है।
  • डेटा को सीधे IO डिवाइस और मेमोरी के बीच स्थानांतरित किया जाता है।
  • कर्नेल इसे एक सिंक्रोनस, ब्लॉकिंग सिस्टम कॉल में लपेटता है।
  • Node.js एक थ्रेड में ब्लॉकिंग सिस्टम कॉल को लपेटता है।

यह सिर्फ सादा बेवकूफ और अक्षम है। लेकिन यह कम से कम काम करता है! हम Node.js का आनंद ले सकते हैं क्योंकि यह एक घटना-चालित अतुल्यकालिक वास्तुकला के पीछे बदसूरत और बोझिल विवरण छुपाता है।

शायद कोई भविष्य में फ़ाइलों के लिए O_NONBLOCK को लागू करेगा? ...

संपादित करें: मैंने एक दोस्त के साथ इस पर चर्चा की और उसने मुझे बताया कि थ्रेड्स का एक विकल्प चुनिंदा के साथ मतदान कर रहा है : 0 का एक समय-निर्धारण निर्दिष्ट करें और लौटे फ़ाइल डिस्क्रिप्टर पर IO करें (अब वे ब्लॉक नहीं करने की गारंटी हैं)।


विंडोज के बारे में क्या?
पचेरियर

क्षमा करें, कोई विचार नहीं। मुझे केवल इतना पता है कि अतुल्यकालिक काम करने के लिए लिबव प्लेटफॉर्म-न्यूट्रल लेयर है। नोड की शुरुआत में कोई लिबाव नहीं था। तब यह लिबव से अलग होने का निर्णय लिया गया और इससे प्लेटफॉर्म-विशिष्ट कोड आसान हो गया। दूसरे शब्दों में, विंडोज की अपनी एक अतुल्यकालिक कहानी है जो शायद लिनक्स से पूरी तरह से अलग हो सकती है, लेकिन हमारे लिए यह कोई फर्क नहीं पड़ता क्योंकि libuv हमारे लिए कड़ी मेहनत करता है।
nalply 15

28

मुझे डर है कि मैं यहां "गलत काम कर रहा हूं", अगर ऐसा है तो मुझे हटा दें और मैं माफी मांगता हूं। विशेष रूप से, मैं यह देखने में विफल रहता हूं कि मैं कुछ लोगों द्वारा बनाए गए स्वच्छ छोटे एनोटेशन कैसे बनाऊं। हालाँकि, इस धागे को बनाने के लिए मेरे पास कई चिंताएं / अवलोकन हैं।

1) लोकप्रिय जवाबों में से एक में छद्म कोड में टिप्पणी वाला तत्व

result = query( "select smurfs from some_mushroom" );
// twiddle fingers
go_do_something_with_result( result );

अनिवार्य रूप से फर्जी है। यदि थ्रेड कंप्यूटिंग कर रहा है, तो यह अंगूठे को मोड़ नहीं रहा है, यह आवश्यक काम कर रहा है। यदि, दूसरी ओर, यह केवल IO के पूरा होने की प्रतीक्षा कर रहा है, तो यह नहीं है CPU समय का उपयोग कर रहा है, कर्नेल में थ्रेड कंट्रोल इन्फ्रास्ट्रक्चर का पूरा बिंदु यह है कि सीपीयू को कुछ उपयोगी मिलेगा। यहाँ सुझाव दिया गया है कि "अपने अंगूठे को मोड़ने" का एकमात्र तरीका एक मतदान लूप बनाना होगा, और जिसने किसी वास्तविक वेबसर्वर को कोड नहीं किया है वह ऐसा करने के लिए पर्याप्त अयोग्य है।

2) "थ्रेड्स हार्ड हैं", केवल डेटा शेयरिंग के संदर्भ में समझ में आता है। यदि आपके पास अनिवार्य रूप से स्वतंत्र धागे हैं जैसे कि स्वतंत्र वेब अनुरोधों को संभालते समय मामला है, तो थ्रेडिंग तुच्छ सरल है, आप बस एक काम को संभालने के रैखिक प्रवाह को कोड करते हैं, और यह जानते हुए बैठते हैं कि यह कई अनुरोधों को संभाल लेगा, और प्रत्येक प्रभावी रूप से स्वतंत्र होगा। व्यक्तिगत रूप से, मैं उद्यम करूंगा कि अधिकांश प्रोग्रामर के लिए, क्लोजर / कॉलबैक मैकेनिज्म सीखना केवल टॉप टू बॉटम थ्रेड वर्जन को कोड करने की तुलना में अधिक जटिल है। (लेकिन हां, अगर आपको थ्रेड्स के बीच संवाद करना है, तो जीवन वास्तव में बहुत तेजी से कठिन हो जाता है, लेकिन फिर मैं इस बात से सहमत नहीं हूं कि क्लोजर / कॉलबैक तंत्र वास्तव में बदल जाता है, यह सिर्फ आपके विकल्पों को प्रतिबंधित करता है, क्योंकि यह दृष्टिकोण थ्रेड्स के साथ अभी भी प्राप्त करने योग्य है , वैसे भी, '

3) अब तक, किसी ने भी कोई वास्तविक सबूत प्रस्तुत नहीं किया है कि एक विशेष प्रकार का संदर्भ स्विच किसी अन्य प्रकार की तुलना में अधिक या कम समय लेने वाला क्यों होगा। मल्टी-टास्किंग कर्नेल बनाने में मेरा अनुभव (एम्बेडेड नियंत्रकों के लिए एक छोटे पैमाने पर, "वास्तविक" ओएस के रूप में इतना फैंसी कुछ भी नहीं है) सुझाव देता है कि यह मामला नहीं होगा।

4) उन सभी दृष्टांतों को जो मैंने उस तिथि को दर्शाने के लिए देखे हैं कि अन्य वेबसर्वरों की तुलना में नोड कितना तेज है, बुरी तरह से त्रुटिपूर्ण हैं, हालांकि, वे एक तरह से दोषपूर्ण हैं जो अप्रत्यक्ष रूप से एक लाभ का वर्णन करता है जिसे मैं निश्चित रूप से नोड के लिए स्वीकार करूंगा (और यह नगण्य है)। नोड की ज़रूरत नहीं लगती (न ही अनुमति भी, वास्तव में) ट्यूनिंग। यदि आपके पास एक थ्रेडेड मॉडल है, तो आपको अपेक्षित लोड को संभालने के लिए पर्याप्त थ्रेड्स बनाने की आवश्यकता है। इसे बुरी तरह से करें, और आप खराब प्रदर्शन के साथ समाप्त करेंगे। यदि बहुत कम धागे हैं, तो सीपीयू निष्क्रिय है, लेकिन अधिक अनुरोधों को स्वीकार करने में असमर्थ है, बहुत सारे थ्रेड्स बनाएं, और आप कर्नेल मेमोरी को बर्बाद कर देंगे, और जावा वातावरण के मामले में, आप मुख्य हीप मेमोरी को बर्बाद कर देंगे । अब, जावा के लिए, हीप को बर्बाद करना सिस्टम के प्रदर्शन को खराब करने का पहला, सबसे अच्छा तरीका है, क्योंकि कुशल कचरा संग्रह (वर्तमान में, यह जी 1 के साथ बदल सकता है, लेकिन ऐसा लगता है कि जूरी अभी भी उस बिंदु पर बाहर है क्योंकि 2013 की शुरुआत में कम से कम) बहुत सारे अतिरिक्त ढेर होने पर निर्भर करता है। तो, यह मुद्दा है, इसे कुछ थ्रेड्स के साथ ट्यून करें, आपके पास बेकार सीपीयू और खराब थ्रूपुट है, इसे बहुत सारे के साथ ट्यून करें, और यह अन्य तरीकों से बोगी करता है।

5) एक और तरीका है जिसमें मैं इस दावे के तर्क को स्वीकार करता हूं कि नोड का दृष्टिकोण "डिजाइन द्वारा तेज है", और यही वह है। अधिकांश थ्रेड मॉडल एक टाइम-स्लाइस किए गए संदर्भ स्विच मॉडल का उपयोग करते हैं, जो कि अधिक उपयुक्त (मूल्य निर्णय चेतावनी :) और अधिक कुशल (मूल्य निर्णय नहीं) प्रीमेप्टिव मॉडल के शीर्ष पर स्तरित होता है। यह दो कारणों से होता है, पहला, अधिकांश प्रोग्रामर को प्राथमिकता के बारे में समझ में नहीं आता है, और दूसरा, अगर आप विंडोज़ के वातावरण में थ्रेडिंग सीखते हैं, तो यह सवाल उठता है कि क्या आपको यह पसंद है या नहीं (बेशक, यह पहले बिंदु को पुष्ट करता है , विशेष रूप से, जावा के पहले संस्करणों ने सोलारिस कार्यान्वयन और विंडोज में गुणा करने पर प्राथमिकता से पूर्व उपयोग किया था। क्योंकि अधिकांश प्रोग्रामर समझ नहीं पाए और शिकायत की कि "थ्रेडिंग सोलारिस में काम नहीं करता है"। उन्होंने हर जगह मॉडल को बदल दिया)। वैसे भी, लब्बोलुआब यह है कि गुणा करना अतिरिक्त (और संभावित अनावश्यक) संदर्भ स्विच बनाता है। प्रत्येक संदर्भ स्विच सीपीयू समय लेता है, और उस समय को उस कार्य से प्रभावी रूप से हटा दिया जाता है जिसे वास्तविक नौकरी पर हाथ में लिया जा सकता है। हालाँकि, समय-समय पर परिसमापन के कारण निवेश की मात्रा समग्र समय के बहुत छोटे प्रतिशत से अधिक नहीं होनी चाहिए, जब तक कि कुछ बहुत बड़ा नहीं हो रहा है, और ऐसा कोई कारण नहीं है कि मैं उम्मीद कर सकूं कि मामला कुछ ही समय में हो सकता है। सरल वेबसर्वर)। तो, हाँ, गुणा करने में शामिल अतिरिक्त संदर्भ स्विच अक्षम हैं (और ये नहीं होते हैं और उस समय को उस कार्य से प्रभावी रूप से हटा दिया जाता है जिसे वास्तविक नौकरी पर किया जा सकता है। हालाँकि, समय-समय पर संदर्भ स्विचिंग के कारण निवेश किया गया समय समग्र समय के बहुत छोटे प्रतिशत से अधिक नहीं होना चाहिए, जब तक कि कुछ बहुत सुंदर नहीं हो रहा हो, और ऐसा कोई कारण नहीं है कि मैं यह उम्मीद कर सकूं कि कुछ ही समय में सरल वेबसर्वर)। तो, हाँ, टाइमिंग में शामिल अतिरिक्त संदर्भ स्विच अक्षम हैं (और ये नहीं होते हैं और उस समय को उस कार्य से प्रभावी रूप से हटा दिया जाता है जिसे वास्तविक नौकरी पर किया जा सकता है। हालाँकि, समय-समय पर संदर्भ स्विचिंग के कारण निवेश किया गया समय समग्र समय के बहुत छोटे प्रतिशत से अधिक नहीं होना चाहिए, जब तक कि कुछ बहुत सुंदर नहीं हो रहा हो, और ऐसा कोई कारण नहीं है कि मैं यह उम्मीद कर सकूं कि कुछ ही समय में सरल वेबसर्वर)। तो, हाँ, टाइमिंग में शामिल अतिरिक्त संदर्भ स्विच अक्षम हैं (और ये नहीं होते हैंएक नियम के रूप में कर्नेल थ्रेड्स, btw) लेकिन अंतर कुछ प्रतिशत थ्रूपुट का होगा, न कि उस तरह के पूरे नंबर के कारक जो प्रदर्शन के दावों में निहित होते हैं जो अक्सर नोड के लिए निहित होते हैं।

वैसे भी, उस सब के लिए क्षमा याचना लंबे समय से और तेजतर्रार है, लेकिन मुझे वास्तव में लगता है कि अब तक, चर्चा कुछ भी साबित नहीं हुई है, और मुझे इन स्थितियों में से किसी में सुनकर खुशी होगी:

a) नोड क्यों बेहतर होना चाहिए इसकी एक वास्तविक व्याख्या (ऊपर जिन दो परिदृश्यों के ऊपर मैंने उल्लिखित किया है, उनमें से पहला (खराब ट्यूनिंग) मेरा मानना ​​है कि मैंने अब तक देखे गए सभी परीक्षणों के लिए वास्तविक स्पष्टीकरण दिया है। ([संपादित करें) ], वास्तव में, जितना अधिक मैं इसके बारे में सोचता हूं, अगर मैं सोच रहा हूं कि बड़ी संख्या में ढेर द्वारा उपयोग की जाने वाली मेमोरी यहां महत्वपूर्ण हो सकती है। आधुनिक थ्रेड्स के लिए डिफ़ॉल्ट स्टैक का आकार बहुत बड़ा है, लेकिन स्मृति द्वारा आवंटित किया गया है। क्लोजर-आधारित ईवेंट सिस्टम केवल वही होगा जो आवश्यक है)

ख) एक वास्तविक बेंचमार्क जो वास्तव में पसंद के थ्रेडेड सर्वर को उचित मौका देता है। कम से कम इस तरह, मुझे यह विश्वास करना बंद करना होगा कि दावे अनिवार्य रूप से झूठे हैं;> ([संपादित करें] जो संभवतः मेरे इरादे से अधिक मजबूत है, लेकिन मुझे लगता है कि प्रदर्शन लाभ के लिए दिए गए स्पष्टीकरण सबसे अच्छे हैं, और बिल्कुल भी अधूरे हैं दिखाए गए बेंचमार्क अनुचित हैं)।

चीयर्स, टोबी


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

3
लेकिन नोड थ्रेड्स के साथ दूर नहीं कर रहा है। यह अभी भी आईओ कार्यों के लिए आंतरिक रूप से उनका उपयोग करता है, जो कि अधिकांश वेब अनुरोधों की आवश्यकता होती है।
लेवी

1
इसके अलावा नोड स्टोर कॉलबैक की रैम में बंद हो जाता है, इसलिए मैं यह नहीं देख सकता कि यह कहां जीतता है।
ऑलेक्ज़ेंडर पापचेंको

@ लेवी लेकिन नोडजेज "अनुरोध के अनुसार एक धागा" का उपयोग नहीं करते हैं। यह एक IO थ्रेडपूल का उपयोग करता है, शायद अतुल्यकालिक IO एपीआई (और शायद POSIX open()को गैर-अवरोधक नहीं बनाया जा सकता है?) का उपयोग करने के साथ जटिलता से बचने के लिए । इस तरह, यह किसी भी प्रदर्शन हिट को संशोधित करता है जहां पारंपरिक fork()/ pthread_create()-ऑन-रिक्वेस्ट मॉडल को थ्रेड्स बनाने और नष्ट करने होंगे। और, जैसा कि पोस्टस्क्रिप्ट a में उल्लेख किया गया है, यह स्टैक स्पेस समस्या को भी संशोधित करता है। आप कह सकते हैं कि हजारों अनुरोधों के साथ, 16 IO थ्रेड्स ठीक हैं।
binki

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

14

मुझे समझ में नहीं आता कि यह बात है कि Node.js अभी भी थ्रेड का उपयोग कर रहा है।

रयान उन हिस्सों के लिए थ्रेड्स का उपयोग करता है जो अवरुद्ध हैं (अधिकांश नोड। जेएस गैर-अवरुद्ध IO का उपयोग करता है) क्योंकि कुछ भागों को गैर-अवरोधक लिखना मुश्किल है। लेकिन मेरा मानना ​​है कि रेयान की इच्छा सब कुछ गैर-अवरुद्ध करने की है। पर स्लाइड 63 (आंतरिक डिजाइन) आप रयान का उपयोग करता है को देखने के libev गैर रोकने के लिए (पुस्तकालय कि अतुल्यकालिक घटना अधिसूचना सार) eventloop । ईवेंट-लूप नोड की वजह से .js को कम थ्रेड्स की आवश्यकता होती है जो संदर्भ स्विचिंग, मेमोरी खपत आदि को कम करता है।


11

थ्रेड्स का उपयोग केवल अतुल्यकालिक सुविधा जैसे कार्यों से निपटने के लिए किया जाता है stat()

stat()समारोह हमेशा ब्लॉक कर रहा है, इसलिए जरूरत है Node.js मुख्य थ्रेड (घटना पाश) को रोके बिना वास्तविक कॉल प्रदर्शन करने के लिए एक धागा उपयोग करने के लिए। संभावित रूप से, थ्रेड पूल से कोई भी धागा कभी भी उपयोग नहीं किया जाएगा यदि आपको उन प्रकार के फ़ंक्शन को कॉल करने की आवश्यकता नहीं है।


7

मुझे नोड.जेएस के आंतरिक कामकाज के बारे में कुछ भी नहीं पता है, लेकिन मैं देख सकता हूं कि इवेंट लूप का उपयोग करके I / O हैंडलिंग को कैसे बेहतर बनाया जा सकता है। एक डिस्क अनुरोध की कल्पना करें, मुझे staticFile.x दें, इसे उस फ़ाइल के लिए 100 अनुरोध करें। प्रत्येक अनुरोध सामान्य रूप से एक थ्रेड को पुनर्जीवित करने में लेता है, जो कि 100 थ्रेड्स है।

अब एक थ्रेड बनाने के पहले अनुरोध की कल्पना करें जो एक प्रकाशक ऑब्जेक्ट बन जाता है, सभी 99 अन्य अनुरोध पहले देखते हैं कि क्या staticFile.x के लिए एक प्रकाशक ऑब्जेक्ट है, यदि हां, तो इसे काम करते समय इसे सुनें, अन्यथा एक नया धागा शुरू करें और इस तरह एक नई प्रकाशक वस्तु।

एक बार सिंगल धागा हो जाने के बाद, यह staticFile.x को सभी 100 श्रोताओं के पास भेज देता है और स्वयं को नष्ट कर देता है, इसलिए अगला अनुरोध एक नया नया थ्रेड और प्रकाशक ऑब्जेक्ट बनाता है।

तो यह उपरोक्त उदाहरण में 100 धागे बनाम 1 धागा है, लेकिन 100 डिस्क लुकअप के बजाय 1 डिस्क लुकअप भी है, लाभ काफी असाधारण हो सकता है। रेयान एक स्मार्ट लड़का है!

देखने का एक और तरीका फिल्म की शुरुआत में उसका एक उदाहरण है। के बजाय:

pseudo code:
result = query('select * from ...');

फिर से, एक डेटाबेस से 100 अलग-अलग प्रश्नों को ...:

pseudo code:
query('select * from ...', function(result){
    // do stuff with result
});

यदि कोई क्वेरी पहले से ही चल रही थी, तो अन्य समान क्वेरीज़ केवल बैंडवागन पर कूदेंगी, इसलिए आप एकल डेटाबेस राउंडट्रिप में 100 क्वेरी कर सकते हैं।


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

यह केवल एक सार उदाहरण है कि यह समझाने के लिए कि कैसे इवेंट लूप अधिक दक्षता प्रदान कर सकते हैं, नोडज बिना डीबी के अतिरिक्त मॉड्यूल के साथ कुछ भी नहीं करते हैं;)
BGerrissen

1
हाँ, मेरी टिप्पणी एक एकल डेटाबेस राउंडट्रिप में 100 प्रश्नों की ओर थी। : p
तोर वालमो

2
हाय BGerrissen: अच्छा पोस्ट। इसलिए, जब कोई क्वेरी निष्पादित हो रही है, तो इसी तरह के अन्य प्रश्न "श्रोता" जैसे staticFile.X उदाहरण से ऊपर होंगे? उदाहरण के लिए, 100 उपयोगकर्ता एक ही क्वेरी प्राप्त करते हैं, केवल एक क्वेरी निष्पादित की जाएगी और अन्य 99 पहले वाले को सुन रहे होंगे? धन्यवाद !
चप्पा

1
आप इसे ध्वनि की तरह बना रहे हैं जैसे नोडज स्वचालित रूप से फ़ंक्शन कॉल या कुछ को याद करते हैं। अब, क्योंकि आपको जावास्क्रिप्ट के इवेंट लूप मॉडल में साझा मेमोरी सिंक्रनाइज़ेशन के बारे में चिंता करने की आवश्यकता नहीं है, इसलिए मेमोरी में चीजों को सुरक्षित रूप से कैश करना आसान है। लेकिन इसका मतलब यह नहीं है कि नोडजेज़ जादुई रूप से आपके लिए है या यह इस प्रकार का प्रदर्शन बढ़ाने के बारे में पूछा जा रहा है।
binki
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.