c++ अभिनेता मॉडल: एरलांग विशेष क्यों है? या, इसके लिए आपको दूसरी भाषा क्यों चाहिए?




concurrency erlang (5)

सी ++ के लिए वास्तविक अभिनेता पुस्तकालय हैं:

और अन्य भाषाओं के लिए कुछ पुस्तकालयों की एक सूची

मैं एर्लांग सीखने में देख रहा हूं, और नतीजतन, अभिनेता मॉडल के बारे में पढ़ रहा है (ठीक है, स्किमिंग)।

जो मैं समझता हूं, उससे अभिनेता मॉडल केवल कार्यों का एक सेट है (एरलांग में "प्रक्रियाओं" नामक हल्के धागे के भीतर चलाया जाता है), जो संदेश को गुजरने के माध्यम से एक-दूसरे के साथ संवाद करता है।

यह सी ++, या किसी अन्य भाषा में लागू करने के लिए काफी तुच्छ लगता है:

class BaseActor {
    std::queue<BaseMessage*> messages;
    CriticalSection messagecs;
    BaseMessage* Pop();
public:
    void Push(BaseMessage* message)
    {
        auto scopedlock = messagecs.AquireScopedLock();
        messagecs.push(message);
    }
    virtual void ActorFn() = 0;
    virtual ~BaseActor() {} = 0;
}

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

अब, मैं समझता हूं कि मैं गायब हूं, या बल्कि, एक महत्वपूर्ण मुद्दे पर चमक रहा हूं, अर्थात्: उपज की कमी का मतलब है कि एक एकल अभिनेता अत्यधिक समय का गलत तरीके से उपभोग कर सकता है। लेकिन क्या क्रॉस-प्लेटफॉर्म कोरआउटिन प्राथमिक चीज है जो इसे सी ++ में कठिन बनाता है? (उदाहरण के लिए विंडोज़ फाइबर हैं।)

क्या मैं कुछ और याद कर रहा हूं, हालांकि, या मॉडल वास्तव में यह स्पष्ट है?

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


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

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

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

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

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

तो यह वास्तव में एरलांग, भाषा, इसके रनटाइम और ओटीपी के बारे में पहले से मौजूद नहीं है, बल्कि एक साफ तरीके से व्यक्त किया जा रहा है, और किसी अन्य भाषा में इसके करीब कुछ भी लागू करना बेहद मुश्किल है। ओटीपी का पालन करने के लिए सिर्फ एक कठिन कार्य है। उसी नस में, हमें वास्तव में सी ++ की आवश्यकता नहीं है, या तो हम कच्चे बाइनरी इनपुट, ब्रेनफक से चिपके रह सकते हैं और असेंबलर को हमारी उच्च स्तरीय भाषा पर विचार कर सकते हैं। हमें ट्रेनों या जहाजों की भी आवश्यकता नहीं है, क्योंकि हम सभी जानते हैं कि कैसे चलना और तैरना है।

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


सी ++ कोड निष्पक्षता, अलगाव, गलती का पता लगाने या वितरण से निपटता नहीं है जो सभी चीजें हैं जो एरलांग अपने अभिनेता मॉडल के हिस्से के रूप में लाती हैं।

  • किसी भी अभिनेता को किसी अन्य अभिनेता (निष्पक्षता) को भूखा होने की अनुमति नहीं है
  • अगर एक अभिनेता दुर्घटनाग्रस्त हो जाता है, तो उसे केवल उस अभिनेता (अलगाव) को प्रभावित करना चाहिए
  • यदि एक अभिनेता दुर्घटनाग्रस्त हो जाता है, तो अन्य अभिनेताओं को उस दुर्घटना का पता लगाने और प्रतिक्रिया करने में सक्षम होना चाहिए (गलती का पता लगाना)
  • अभिनेताओं को नेटवर्क पर संवाद करने में सक्षम होना चाहिए जैसे कि वे एक ही मशीन (वितरण) पर थे

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

इसके अलावा एरलांग में लिखे गए सभी पुस्तकालयों और औजारों का मानना ​​है कि यह वही तरीका है जो दुनिया काम करता है और तदनुसार डिजाइन किया गया है।

इन चीजों को सी ++ में करना असंभव नहीं है, लेकिन यदि आप इस तथ्य को जोड़ते हैं कि एरलांग लगभग सभी प्रमुख एचडब्ल्यू और ओएस कॉन्फ़िगरेशन पर काम करता है तो वे तेजी से कठिन हो जाते हैं।

संपादित करें: Ulf Wiger द्वारा एर्लांग शैली समरूपता को देखते हुए बस एक विवरण मिला।


यह वास्तव में एक उत्कृष्ट सवाल है, और उत्कृष्ट उत्तरों प्राप्त हुए हैं जो शायद अभी तक असुविधाजनक हैं।

पहले से ही यहां दिए गए अन्य महान उत्तरों के लिए छाया और जोर जोड़ने के लिए, गलती सहनशीलता और अपटाइम प्राप्त करने के लिए एर्लांग क्या लेता है (पारंपरिक सामान्य प्रयोजन भाषाओं की तुलना में सी / सी ++) की तुलना में विचार करें।

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

किसी भी मामले में, आपकी प्रक्रिया दुर्घटना ने अब पूरी प्रणाली को प्रगति करने से रोक दिया है। Fini। कहानी का अंत। आपका सिस्टम मर चुका है जब तक आप गारंटी नहीं दे सकते कि आप सी / सी ++ में उपयोग की जाने वाली प्रत्येक लाइब्रेरी को कभी भी मॉलोक नहीं कहते हैं और कभी भी लॉक प्राप्त नहीं करते हैं, तो आपका सिस्टम गलती सहनशील नहीं है। Erlang सिस्टम इच्छानुसार प्रक्रियाओं को मार सकते हैं और कर सकते हैं जब क्रम में भारी भार प्रगति करता है, इसलिए पैमाने पर आपके एरलांग प्रक्रियाओं को थ्रूपुट को बनाए रखने के लिए मारने योग्य (निष्पादन के किसी भी बिंदु पर) होना चाहिए।

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

दूसरा, एरलांग स्थैतिक टाइपिंग ले जाता है, जो बदले में गर्म कोड स्वैपिंग सक्षम करता है और एक ही कोड के दो संस्करणों को एक साथ चलाता है। इसका मतलब है कि आप सिस्टम को रोक दिए बिना रनटाइम पर अपना कोड अपग्रेड कर सकते हैं। इस प्रकार सिस्टम नौ 9 या 32 एमसीसी डाउनटाइम / वर्ष के लिए बने रहते हैं। वे बस जगह में अपग्रेड कर रहे हैं। अपग्रेड करने के लिए आपके C ++ फ़ंक्शंस को मैन्युअल रूप से फिर से लिंक करना होगा, और एक ही समय में दो संस्करणों को चलाने के लिए समर्थित नहीं है। कोड अपग्रेड के लिए सिस्टम डाउनटाइम की आवश्यकता होती है, और यदि आपके पास एक बड़ा क्लस्टर है जो कोड के एक से अधिक संस्करणों को एक साथ नहीं चला सकता है, तो आपको पूरे क्लस्टर को एक बार में ले जाना होगा। आउच। और दूरसंचार दुनिया में, सहनशील नहीं है।

इसके अलावा एरलांग साझा स्मृति लेता है और साझा कचरा संग्रह साझा करता है; प्रत्येक हल्के वजन की प्रक्रिया कचरा स्वतंत्र रूप से एकत्र की जाती है। यह पहली बिंदु का एक सरल विस्तार है, लेकिन वास्तविक गलती सहनशीलता के लिए आपको जोर देता है कि आपको उन प्रक्रियाओं की आवश्यकता है जो निर्भरताओं के संदर्भ में अंतःस्थापित नहीं हैं। इसका मतलब है कि जावा की तुलना में आपके जीसी विराम बड़े सिस्टम के लिए सहनशील (8 जीबी जीसी के लिए आधा घंटे रुकने के बजाय छोटे) हैं।


मैं खुद को उद्धृत नहीं करना चाहता, लेकिन प्रोग्रामिंग के विर्डिंग के पहले नियम से

किसी अन्य भाषा में किसी भी पर्याप्त जटिल समवर्ती कार्यक्रम में विज्ञापन के अनौपचारिक रूप से निर्दिष्ट बग-सवार धीमे कार्यान्वयन का आधा हिस्सा है।

ग्रीन्सपुन के संबंध में। जो (आर्मस्ट्रांग) का एक समान नियम है।

समस्या अभिनेताओं को लागू नहीं करना है, यह मुश्किल नहीं है। समस्या यह है कि सबकुछ एक साथ काम कर रहा है: प्रक्रियाओं, संचार, कचरा संग्रह, भाषा प्राइमेटिव्स, एरर हैंडलिंग इत्यादि ... उदाहरण के लिए ओएस थ्रेड्स का उपयोग करके बुरी तरह से स्केल करता है ताकि आपको इसे स्वयं करने की आवश्यकता हो। यह एक ओओ भाषा "बेचने" की कोशिश की तरह होगा जहां आप केवल 1k ऑब्जेक्ट्स प्राप्त कर सकते हैं और वे बनाने और उपयोग करने के लिए भारी हैं। हमारे दृष्टिकोण से समेकन अनुप्रयोगों की संरचना के लिए मूल अमूर्त है।

दूर ले जा रहा है तो मैं यहाँ रुक जाऊंगा।





message-passing