क्या एसिंक्स प्रक्रियाओं के लिए एक स्टैक संरचना का उपयोग किया जाता है?


10

इस सवाल का एक उत्कृष्ट जवाब है एरिक लिपर्ट ने बताया कि स्टैक का उपयोग किस लिए किया जाता है। वर्ष के लिए मुझे पता है - आम तौर पर बोलना - स्टैक क्या है और इसका उपयोग कैसे किया जाता है, लेकिन उनके जवाबों के कुछ हिस्सों ने मुझे आश्चर्यचकित किया है कि अगर यह स्टैक संरचना आज कम उपयोग की जाती है जहां async प्रोग्रामिंग आदर्श है।

उनके जवाब से:

स्टैक कॉरआउट्स के बिना किसी भाषा में निरंतरता के संशोधन का हिस्सा है।

विशेष रूप से, इस के बिना coroutines हिस्से ने मुझे आश्चर्यचकित किया है।

वह यहाँ कुछ और समझाता है:

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

यह स्टैक के संबंध में उत्कृष्ट है, लेकिन मुझे एक अनुत्तरित प्रश्न के साथ छोड़ देता है कि क्या संरचना का उपयोग किया जाता है जब स्टैक इन भाषा सुविधाओं को संभालने के लिए बहुत सरल होता है जिन्हें अधिक उन्नत डेटा संरचनाओं की आवश्यकता होती है?

जैसे-जैसे तकनीक आगे बढ़ रही है, क्या स्टैक दूर होता जा रहा है? इसकी जगह क्या लेता है? क्या यह संकर किस्म है? (उदाहरण के लिए, क्या मेरा .NET प्रोग्राम तब तक एक स्टैक का उपयोग करता है जब तक कि यह एक एसिंक्स कॉल को हिट नहीं करता है, तब तक किसी अन्य संरचना पर स्विच हो जाता है, जब तक कि स्टैक वापस उस स्थिति में नहीं आता है जहां यह अगले आइटमों के बारे में सुनिश्चित हो सकता है, आदि? )

इन परिदृश्यों के लिए बहुत उन्नत हैं एक स्टैक सही समझ में आता है, लेकिन स्टैक की जगह क्या है? जब मैंने इस साल पहले के बारे में सीखा था, तो स्टैक वहां था क्योंकि यह बहुत तेज़ और हल्का था, ढेर से दूर आवेदन पर आवंटित स्मृति का एक टुकड़ा क्योंकि यह हाथ में काम के लिए अत्यधिक कुशल प्रबंधन का समर्थन करता था (सजा का इरादा?)। क्या बदला है?

जवाबों:


14

क्या यह संकर किस्म है? (उदाहरण के लिए, क्या मेरा .NET प्रोग्राम तब तक एक स्टैक का उपयोग करता है जब तक कि यह एक एसिंक्स कॉल को हिट नहीं करता है, तब तक किसी अन्य संरचना पर स्विच हो जाता है, जब तक कि स्टैक वापस उस स्थिति में नहीं आता है जहां यह अगले आइटमों के बारे में सुनिश्चित हो सकता है, आदि? )

मूल रूप से हाँ।

मान लीजिए हमारे पास है

async void MyButton_OnClick() { await Foo(); Bar(); }
async Task Foo() { await Task.Delay(123); Blah(); }

यहाँ एक बहुत ही सरल विवरण दिया गया है कि कैसे निरंतरता को पुन: परिभाषित किया जाता है। वास्तविक कोड काफी अधिक जटिल है, लेकिन इससे विचार पार हो जाता है।

आप बटन पर क्लिक करें। एक संदेश कतारबद्ध है। संदेश लूप संदेश को संसाधित करता है और स्टैक पर संदेश कतार का रिटर्न एड्रेस डालते हुए क्लिक हैंडलर को कॉल करता है। यानी हैंडलर करने के बाद जो चीज होती है वह यह है कि मैसेज लूप को चालू रखना है। तो हैंडलर की निरंतरता लूप है।

स्टैक पर खुद का रिटर्न एड्रेस डालते हुए क्लिक हैंडलर फू () कहता है। यही है, फू की निरंतरता क्लिक हैंडलर के शेष है।

फू टास्क को बुलाता है। डेल, स्टैक पर खुद का रिटर्न एड्रेस डालते हुए।

Task.Delay जो भी जादू करता है उसे तुरंत एक टास्क को वापस करने की आवश्यकता होती है। स्टैक आबाद है और हम फू में वापस आ गए हैं।

फू अपने काम को पूरा करने के लिए लौटा हुआ कार्य देखता है। यह नहीं। प्रतीक्षारत की निरंतरता ब्लाह () को कॉल करने के लिए है, इसलिए फू एक प्रतिनिधि बनाता है जो ब्लाह को बुलाता है (), और संकेत देता है कि कार्य की निरंतरता के रूप में। (मैंने अभी थोड़ा गलत बयान दिया है; क्या आपने इसे पकड़ा है? यदि नहीं, तो हम इसे एक पल में प्रकट कर देंगे।)

फू तब अपनी टास्क ऑब्जेक्ट बनाता है, इसे अपूर्ण के रूप में चिह्नित करता है, और इसे स्टैक को क्लिक हैंडलर को वापस करता है।

क्लिक हैंडलर फू के कार्य की जांच करता है और उसे पता चलता है कि यह अपूर्ण है। हैंडलर में प्रतीक्षा की निरंतरता बार () को कॉल करना है, इसलिए क्लिक हैंडलर एक प्रतिनिधि बनाता है जो बार () को कॉल करता है और इसे फू () द्वारा लौटाए गए कार्य की निरंतरता के रूप में सेट करता है। इसके बाद मैसेज लूप को स्टैक वापस करता है।

संदेश लूप संदेशों को संसाधित करता रहता है। आखिरकार देरी कार्य द्वारा बनाया गया टाइमर जादू अपनी बात करता है और कतार को एक संदेश पोस्ट करता है जो कहता है कि विलंब कार्य की निरंतरता अब निष्पादित की जा सकती है। इसलिए मैसेज लूप कार्य को निरंतरता कहता है, हमेशा की तरह स्टैक पर। उस प्रतिनिधि को ब्लाह कहते हैं ()। ब्लाह () जो करता है वही करता है और स्टैक को वापस करता है।

अब क्या होता है? यहाँ मुश्किल सा है। विलंब कार्य की निरंतरता केवल ब्लाह () को नहीं बुलाती है। इसे बार () को कॉल ट्रिगर करना पड़ता है, लेकिन यह कार्य बार के बारे में नहीं जानता है!

फू ने वास्तव में एक प्रतिनिधि बनाया जो (1) ब्ला को बुलाता है (), और (2) उस कार्य की निरंतरता को कहता है जिसे फू ने बनाया और वापस इवेंट हैंडलर को सौंप दिया। इसी तरह हम एक प्रतिनिधि को कॉल करते हैं जो बार () को कॉल करता है।

और अब हमने वह सब कुछ किया है जो हमें सही क्रम में करने की आवश्यकता थी। लेकिन हमने बहुत लंबे समय तक संदेश लूप में संदेशों को संसाधित करना बंद नहीं किया, इसलिए एप्लिकेशन उत्तरदायी रहा।

इन परिदृश्यों के लिए बहुत उन्नत हैं एक स्टैक सही समझ में आता है, लेकिन स्टैक की जगह क्या है?

प्रतिनिधियों के बंद वर्गों के माध्यम से एक दूसरे के संदर्भ में कार्य वस्तुओं का ग्राफ। वे क्लोजर क्लासेस राज्य मशीनें हैं जो सबसे हाल ही में निष्पादित प्रतीक्षा की स्थिति और स्थानीय लोगों के मूल्यों पर नज़र रखती हैं। साथ ही, दिए गए उदाहरण में, ऑपरेटिंग सिस्टम और संदेश लूप द्वारा कार्यान्वित क्रियाओं की एक वैश्विक-राज्य कतार जो उन कार्यों को निष्पादित करती है।

व्यायाम: आप यह कैसे मान लेते हैं कि यह दुनिया में बिना संदेश के काम करता है? उदाहरण के लिए, अनुप्रयोग कंसोल। कंसोल ऐप में इंतजार करना काफी अलग है; क्या आप यह जान सकते हैं कि जो आप अभी तक जानते हैं उससे यह कैसे काम करता है?

जब मैंने इस साल पहले के बारे में सीखा था, तो स्टैक वहां था क्योंकि यह तेज और हल्का था, ढेर से दूर आवेदन पर आवंटित स्मृति का एक टुकड़ा क्योंकि यह हाथ में कार्य के लिए अत्यधिक कुशल प्रबंधन का समर्थन करता था (उद्देश्य?)। क्या बदला है?

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

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


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

3
@ jdl134679: मैं आपको सुझाव दूंगा कि आप किसी चीज़ को उस उत्तर के रूप में चिह्नित करें यदि आपको लगता है कि आपके प्रश्न का उत्तर दिया गया है; यह एक संकेत भेजता है कि लोगों को यहां आना चाहिए अगर वे एक लिखने के बजाय एक अच्छा जवाब पढ़ना चाहते हैं । (निश्चित रूप से अच्छे उत्तर लिखने को हमेशा प्रोत्साहित किया जाता है।) मुझे परवाह नहीं है कि चेकमार्क किसे मिलता है।
एरिक लिपर्ट

8

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

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

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

(दूसरे शब्दों में, स्टैक और हीप के बीच का अंतर धुंधला रहा है, लेकिन पूरे-प्रोग्राम परिवर्तन की आवश्यकता हो सकती है, या कॉलिंग कन्वेंशन और कंपाइलर को असंगत रूप से बदलना )

यह भी देखें इस और है कि और कई कागजात (जैसे यह ) पर चर्चा सीपीएस परिवर्तन। एएसएलआर और कॉल / सीसी के बारे में भी पढ़ें । जारी रखने के बारे में और पढ़ें (& STFW) ।

.CLR और .NET कार्यान्वयन में कई व्यावहारिक कारणों से अत्याधुनिक GC & CPS परिवर्तन नहीं हो सकता है। यह पूरे प्रोग्राम ट्रांसफ़ॉर्म से संबंधित ट्रेड-ऑफ है (और निम्न-स्तरीय सी दिनचर्या का उपयोग करने में आसानी और सी या सी ++ में एक रनटाइम कोडित है)।

चिकन योजना सीपीएस परिवर्तन के साथ एक अपरंपरागत तरीके से मशीन (या सी) स्टैक का उपयोग कर रही है: हर आवंटन स्टैक पर होता है, और जब यह बहुत बड़ा हो जाता है तो एक जेसीली जीसी नकल और अग्रेषण कदम हाल के स्टैक आवंटित मूल्यों को स्थानांतरित करने के लिए होता है (और शायद वर्तमान निरंतरता) ढेर के लिए, और फिर ढेर एक बड़े के साथ काफी कम हो जाता है setjmp


SICP , प्रोग्रामिंग लैंग्वेज प्रैग्मैटिक्स , ड्रैगन बुक , लिस्प इन स्माल पीसेज भी पढ़ें ।


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