Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

Ruby के गारबेज कलेक्शन में गहरी डुबकी: MRI कार्यान्वयन समझाया गया

पिछले Ruby Magic एपिसोड में हमने इस बारे में बात की थी कि हमें गारबेज कलेक्शन (GC) की आवश्यकता क्यों है और यह सामान्य रूप से कैसे काम करता है। इस पोस्ट में हम थोड़ा गहराई से देखेंगे कि यह Ruby में कैसे लागू किया गया है।

विभिन्न Ruby कार्यान्वयन

Ruby के कई कार्यान्वयन हैं। तीन लोकप्रिय हैं: MRI (Matz's Ruby Interpreter), Rubinius और JRuby। विभिन्न Ruby कार्यान्वयन GC के विभिन्न तरीकों का उपयोग करते हैं। इस लेख में हम MRI पर ध्यान केंद्रित करेंगे, जो अधिकांश Ruby डेवलपर्स उपयोग करते हैं।

Ruby का हीप

कंप्यूटर में दो प्रकार की मेमोरी होती है: स्टैक और हीप। स्टैक बहुत तेज़ है और फ़ंक्शन कॉल के संदर्भ के लिए स्थानीय है। इसका मतलब है कि स्टैक में घोषित हर वेरिएबल फ़ंक्शन समाप्त होते ही तुरंत मुक्त हो जाता है। स्टैक आकार में बहुत सीमित है, इसलिए आप बड़ी ऑब्जेक्ट्स को स्टोर नहीं कर सकते जिनमें एक छवि या फ़ाइल का डेटा होता है, उदाहरण के लिए।

यह Ruby ऑब्जेक्ट्स को स्टोर करने के लिए एक बुरा फिट है। ये ऑब्जेक्ट्स अक्सर एक मेथड कॉल से अधिक समय तक चिपके रहते हैं। साथ ही, यह अनुमान लगाना लगभग असंभव है कि कोई ऑब्जेक्ट स्टैक के लिए बहुत बड़ा होगा या नहीं।

इसलिए Ruby दूसरे प्रकार की मेमोरी का उपयोग करता है: हीप। हीप पर एक प्रोग्राम कुछ मेमोरी क्लेम कर सकता है और फिर उस मेमोरी की सफाई के लिए जिम्मेदार होता है जब वह इसके साथ हो जाता है। Ruby इसका उपयोग Ruby ऑब्जेक्ट्स को स्टोर करने के लिए उपयोग की जाने वाली मेमोरी के एक सिंगल स्लैब को क्लेम करके करता है। इसे Ruby के हीप के रूप में संदर्भित किया जाता है।

स्टैक और हीप सारांश
स्टैक मेमोरी बहुत तेज़
उपयोग की गई मेमोरी फ़ंक्शन कॉल समाप्त होने पर स्वचालित रूप से मुक्त हो जाती है
आकार में बहुत सीमित
हीप मेमोरी स्टैक से थोड़ा धीमा
कोई स्वचालित सफाई नहीं
आकार केवल कंप्यूटर की उपलब्ध मेमोरी द्वारा सीमित

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

मार्क और स्वीप

MRI GC एल्गोरिदम का उपयोग करता है जिसे मार्क और स्वीप कहा जाता है। यह पहले मार्क चरण करके संचालित होता है। मार्क चरण में गारबेज कलेक्टर वर्तमान में मौजूद सभी ऑब्जेक्ट्स को स्कैन करता है और हर ऑब्जेक्ट पर एक मार्क्ड फ्लैग सेट करता है जिसे वह मानता है कि साफ किया जा सकता है।

मार्क चरण आपके कोड के निष्पादन को रोक देता है। इसका कारण यह है कि गारबेज कलेक्टर को मौजूद ऑब्जेक्ट्स के बीच सभी संबंधों को समझना होता है। यदि प्रोग्राम मार्क प्रक्रिया के दौरान चल रहा होता तो चीजें बीच में बदल सकती थीं और गारबेज कलेक्टर को यकीन नहीं होता कि किसी ऑब्जेक्ट की वर्तमान स्थिति क्या है।

दूसरे चरण में स्वीप चरण शुरू होता है। यह Ruby 1.9 और ऊपर पर बैकग्राउंड में चलता है। गारबेज कलेक्टर चुपचाप मार्क चरण में मार्क की गई हर ऑब्जेक्ट को मुक्त करता है। मेमोरी केवल स्वीप पूरा होने के बाद फिर से उपलब्ध होती है।

चूंकि मार्क चरण आपके कोड के निष्पादन को रोक देता है, यही वह जगह है जहां प्रोडक्शन में समस्याएं हो सकती हैं। स्वीप चरण अपेक्षाकृत सौम्य है।

मार्क और स्वीप सारांश
मार्क चरण मौजूदा ऑब्जेक्ट्स को स्कैन करता है
मार्क फ्लैग सेट करता है यदि ऑब्जेक्ट को साफ किया जा सकता है
कोड निष्पादन को रोकता है
स्वीप चरण बैकग्राउंड में चलता है
मार्क की गई ऑब्जेक्ट्स को साफ करता है
स्वीप पूरा होने के बाद मेमोरी फिर से उपलब्ध होती है

मेजर और माइनर GC रन

Ruby 2.1+ में गारबेज कलेक्टर मेजर और माइनर रन करता है। यह ट्रैक रखता है कि कौन सी ऑब्जेक्ट्स नई हैं। यदि एक ऑब्जेक्ट कुछ GC रन से बच जाती है तो उसे पुराना मार्क किया जाता है। पुरानी ऑब्जेक्ट्स को फिर माइनर रन में नजरअंदाज किया जाता है। यह माइनर रन को बहुत कम दखलंदाजी वाला बनाता है क्योंकि गारबेज कलेक्टर को केवल उन ऑब्जेक्ट्स को स्कैन करना होता है जिन्हें अभी आवंटित किया गया है।

यह उपयोगी है क्योंकि अक्सर आपकी मेमोरी का एक हिस्सा ऐसा होता है जिसे कभी साफ नहीं किया जाना चाहिए। जब आप Rails को बूट करते हैं तो यह पूरे Rails फ्रेमवर्क को मेमोरी में लोड करता है। यह पूरे जीवनकाल के लिए वहीं रहेगा, इसलिए इन सभी ऑब्जेक्ट्स को हर बार जांचना संसाधनों की बर्बादी होगी।

मेजर और माइनर रन
मेजर रन कम बार चलता है
चलाने के लिए अधिक गहन
माइनर रन पुरानी ऑब्जेक्ट्स को नजरअंदाज करता है
अधिक बार चलता है
चलाने के लिए कम दखलंदाजी वाला

उन लोगों के लिए जो गहराई से गोता लगाना चाहते हैं

हमने अमन गुप्ता के बेहतरीन ब्लॉग से इसके बारे में बहुत कुछ सीखा। यदि आप इस विषय में गहराई से गोता लगाना चाहते हैं तो इसे देखें।

अगला: व्यावहारिक गारबेज कलेक्शन ट्यूनिंग

कई मेट्रिक्स हैं जिन्हें आप माप सकते हैं और कॉन्फ़िगरेशन परिवर्तन जो आप कर सकते हैं ताकि गारबेज कलेक्टर कैसे संचालित होता है इसे ट्यून किया जा सके। इस GC श्रृंखला की अगली किस्त में हम इन मेट्रिक्स और कॉन्फ़िगरेशन पैरामीटर्स पर चर्चा करेंगे।

  1. रूबी इंटरप्रेटर बनाना: भाग 2 – एक कस्टम प्रोग्रामिंग भाषा का निर्माण रूबी इंटरप्रेटर बनाना: भाग 2 – एक कस्टम प्रोग्रामिंग भाषा का निर्माण

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

  1. गूगल TCMalloc के साथ रूबी की मेमोरी आवंटन प्रोफाइलिंग गूगल TCMalloc के साथ रूबी की मेमोरी आवंटन प्रोफाइलिंग

    रूबी में मेमोरी आवंटन कैसे काम करता है? रूबी मेमोरी को चंक्स में प्राप्त करता है, जिन्हें पेज कहा जाता है, नए ऑब्जेक्ट्स यहां सहेजे जाते हैं। फिर… जब ये पेज भर जाते हैं, तो अधिक मेमोरी की आवश्यकता होती है। रूबी malloc फंक्शन के साथ ऑपरेटिंग सिस्टम से अधिक मेमोरी का अनुरोध करता है। यह malloc फंक्शन ऑ

  1. रूबी इंटर्नल्स उजागर: ऑब्जेक्ट मेमोरी लेआउट को समझना रूबी इंटर्नल्स उजागर: ऑब्जेक्ट मेमोरी लेआउट को समझना

    क्या आप रूबी इंटर्नल्स का एक त्वरित दौरा चाहेंगे? तो आप एक ट्रीट के लिए तैयार हैं। क्योंकि... हम एक साथ पता लगाने जा रहे हैं कि एक रूबी ऑब्जेक्ट मेमोरी में कैसे लेआउट होता है और आप कुछ अच्छी चीजें करने के लिए आंतरिक डेटा संरचनाओं में हेरफेर कैसे कर सकते हैं। सीट बेल्ट बांधें और रूबी इंटरप्रेटर की गह