रूबी अनुप्रयोगों में मेमोरी ब्लोट का मुद्दा लगातार चर्चा का विषय है। इस पोस्ट में, हम देखेंगे कि रूबी मेमोरी प्रबंधन कैसे गलत हो सकता है, और आप अपने रूबी एप्लिकेशन को उड़ने से रोकने के लिए क्या कर सकते हैं।
सबसे पहले, हमें यह समझने की जरूरत है कि किसी एप्लिकेशन की मेमोरी के संदर्भ में ब्लोट का क्या अर्थ है।
चलो गोता लगाएँ!
रूबी में मेमोरी ब्लोट क्या है?
मेमोरी ब्लोट तब होता है जब आपके एप्लिकेशन का मेमोरी उपयोग बिना किसी स्पष्ट स्पष्टीकरण के अचानक बढ़ जाता है। यह वृद्धि तेज हो भी सकती है और नहीं भी हो सकती है, लेकिन ज्यादातर मामलों में यह निरंतर हो जाती है। यह एक मेमोरी लीक से अलग है, जो कुछ समय में कई निष्पादन के परिणामस्वरूप होता है।
मेमोरी ब्लोट उत्पादन में आपके रूबी एप्लिकेशन के साथ होने वाली सबसे खराब चीजों में से एक हो सकता है। हालांकि, यदि आप उचित उपाय करते हैं तो इससे बचा जा सकता है। उदाहरण के लिए, यदि आप अपने एप्लिकेशन के मेमोरी उपयोग में स्पाइक देखते हैं, तो अन्य समस्याओं के निवारण से पहले मेमोरी ब्लोट के संकेतों की जांच करना सबसे अच्छा है।
इससे पहले कि हम मेमोरी ब्लोट का निदान और उसे ठीक करने का तरीका जानें, आइए रूबी की मेमोरी आर्किटेक्चर की एक त्वरित वॉकथ्रू लें।
रूबी की मेमोरी स्ट्रक्चर
रूबी का मेमोरी उपयोग विशिष्ट तत्वों के इर्द-गिर्द घूमता है जो उपलब्ध सिस्टम संसाधनों के विवेकपूर्ण उपयोग का प्रबंधन करते हैं। इन तत्वों में रूबी भाषा, होस्ट ऑपरेटिंग सिस्टम और सिस्टम कर्नेल शामिल हैं।
इनके अलावा, रूबी मेमोरी को कैसे प्रबंधित और पुन:उपयोग किया जाता है, यह निर्धारित करने में कचरा संग्रहण प्रक्रिया भी महत्वपूर्ण भूमिका निभाती है।
रूबी हीप पेज और मेमोरी स्लॉट
रूबी भाषा वस्तुओं को हीप पेज नामक खंडों में व्यवस्थित करती है। संपूर्ण हीप स्पेस (उपलब्ध मेमोरी) को प्रयुक्त और खाली वर्गों में विभाजित किया गया है। इन ढेर पृष्ठों को आगे समान आकार के स्लॉट में विभाजित किया जाता है, जो प्रत्येक इकाई के आकार की वस्तु की अनुमति देता है।
किसी नई वस्तु को स्मृति आवंटित करते समय, रूबी पहले खाली स्लॉट के लिए प्रयुक्त ढेर स्थान को देखता है। यदि कोई नहीं मिलता है, तो यह खाली अनुभाग से एक नया हीप पृष्ठ आवंटित करता है।
मेमोरी स्लॉट छोटे मेमोरी लोकेशन होते हैं, प्रत्येक आकार में लगभग 40 बाइट्स होते हैं। इन स्लॉट से ओवरफ्लो होने वाला डेटा हीप पेज के बाहर एक अलग क्षेत्र में संग्रहीत किया जाता है और प्रत्येक स्लॉट बाहरी जानकारी के लिए एक पॉइंटर संग्रहीत करता है।
एक सिस्टम का मेमोरी एलोकेटर रूबी रनटाइम वातावरण में सभी आवंटन करता है, जिसमें हीप पेज और बाहरी डेटा पॉइंटर्स शामिल हैं।
रूबी में ऑपरेटिंग सिस्टम मेमोरी आवंटन
रूबी भाषा द्वारा किए गए मेमोरी आवंटन कॉल को होस्ट ऑपरेटिंग सिस्टम के मेमोरी एलोकेटर द्वारा नियंत्रित और प्रतिक्रिया दी जाती है।
आमतौर पर, मेमोरी एलोकेटर में C फ़ंक्शंस का एक समूह होता है, जिसका नाम है मॉलोक , कॉलोक , realloc , और मुफ़्त . आइए जल्दी से प्रत्येक पर एक नज़र डालें:
- मॉलोक :मैलोक मेमोरी आवंटन के लिए खड़ा है, और इसका उपयोग वस्तुओं को मुफ्त मेमोरी आवंटित करने के लिए किया जाता है। यह आवंटित की जाने वाली मेमोरी के आकार को लेता है और आवंटित मेमोरी ब्लॉक के शुरुआती सूचकांक में एक पॉइंटर लौटाता है।
- कॉलोक :Calloc सन्निहित आवंटन के लिए खड़ा है, और यह रूबी भाषा को स्मृति के लगातार ब्लॉक आवंटित करने की अनुमति देता है। ज्ञात लंबाई के ऑब्जेक्ट सरणियों को आवंटित करते समय यह फायदेमंद होता है।
- रीअलोक :Realloc का अर्थ है पुन:आवंटन, और यह भाषा को एक नए आकार के साथ स्मृति को पुन:आवंटित करने की अनुमति देता है।
- निःशुल्क :स्मृति स्थानों के पूर्व-आवंटित सेट को साफ़ करने के लिए नि:शुल्क का उपयोग किया जाता है। यह एक पॉइंटर को मेमोरी ब्लॉक के शुरुआती इंडेक्स में ले जाता है जिसे मुक्त किया जाना है।
रूबी में कचरा संग्रह
भाषा रनटाइम की कचरा संग्रहण प्रक्रिया नाटकीय रूप से प्रभावित करती है कि वह अपनी उपलब्ध मेमोरी का कितनी अच्छी तरह उपयोग करती है।
रूबी के पास बहुत उन्नत कचरा संग्रह होता है जो हर समय एप्लिकेशन मेमोरी खपत को अनुकूलित करने के लिए ऊपर वर्णित सभी एपीआई विधियों का उपयोग करता है।
रूबी में कचरा संग्रहण प्रक्रिया के बारे में एक दिलचस्प तथ्य यह है कि यह पूरे आवेदन को रोक देता है! यह सुनिश्चित करता है कि कचरा संग्रहण के दौरान कोई नई वस्तु आवंटन नहीं होता है। इस वजह से, आपकी कचरा संग्रहण दिनचर्या कम और जितनी जल्दी हो सके उतनी जल्दी होनी चाहिए।
रूबी में मेमोरी ब्लोट के दो सामान्य कारण
यह खंड रूबी में मेमोरी ब्लोट होने के दो सबसे महत्वपूर्ण कारणों पर चर्चा करेगा:विखंडन और धीमी गति से रिलीज।
स्मृति विखंडन
मेमोरी फ़्रेग्मेंटेशन तब होता है जब मेमोरी में ऑब्जेक्ट एलोकेशन हर जगह बिखरा हुआ होता है, जिससे फ्री मेमोरी के सन्निहित विखंडू की संख्या कम हो जाती है। मेमोरी को बिना सन्निहित ब्लॉक वाली वस्तुओं को आवंटित नहीं किया जा सकता है, भले ही डिस्क पर पर्याप्त से अधिक मुक्त मेमोरी उपलब्ध हो। यह समस्या किसी भी प्रोग्रामिंग भाषा या वातावरण में हो सकती है, और समस्या को हल करने के लिए प्रत्येक भाषा के अपने तरीके हैं।
विखंडन दो अलग-अलग स्तरों पर हो सकता है:भाषा का स्तर और स्मृति आवंटनकर्ता का स्तर। आइए इन दोनों को विस्तार से देखें।
रूबी स्तर पर विखंडन
भाषा स्तर पर विखंडन कचरा संग्रहण प्रक्रिया के डिजाइन के कारण होता है। कचरा संग्रहण प्रक्रिया एक रूबी हीप पेज स्लॉट को मुफ्त के रूप में चिह्नित करती है, जिससे उस स्लॉट का पुन:उपयोग स्मृति में किसी अन्य ऑब्जेक्ट को आवंटित करने की अनुमति देता है। यदि एक पूर्ण रूबी हीप पेज में केवल मुफ्त स्लॉट होते हैं, तो उस हीप पेज को पुन:उपयोग के लिए मेमोरी एलोकेटर को जारी किया जा सकता है।
लेकिन क्या होगा यदि ढेर पर बहुत कम संख्या में स्लॉट मुक्त चिह्नित नहीं हैं? इसे स्मृति आवंटक को वापस जारी नहीं किया जाएगा। अब, कचरा संग्रह द्वारा आवंटित और मुक्त किए गए विभिन्न ढेर पृष्ठों में कई स्लॉट के बारे में सोचें। संपूर्ण हीप पृष्ठों को एक बार में जारी करना असंभव है। भले ही कचरा संग्रहण प्रक्रिया स्मृति को मुक्त कर देती है, स्मृति आवंटनकर्ता द्वारा इसका पुन:उपयोग नहीं किया जा सकता क्योंकि स्मृति ब्लॉक आंशिक रूप से इस पर कब्जा कर लेते हैं।
मेमोरी एलोकेटर स्तर पर विखंडन
स्मृति आवंटक को भी इसी तरह की समस्या का सामना करना पड़ता है:ओएस ढेर को पूरी तरह से मुक्त होने के बाद इसे जारी करना होगा। लेकिन यह असंभव है कि कचरा संग्रहण प्रक्रिया की यादृच्छिक प्रकृति को देखते हुए एक ही बार में संपूर्ण OS हीप को मुक्त किया जा सकता है।
मेमोरी एलोकेटर एक एप्लिकेशन के उपयोग के लिए सिस्टम मेमोरी से ओएस हीप्स का भी प्रावधान करता है। यह केवल नए ओएस ढेर को व्यवस्थित करने के लिए आगे बढ़ेगा, भले ही मौजूदा ढेर में एप्लिकेशन की मेमोरी आवश्यकताओं को पूरा करने के लिए पर्याप्त मुफ्त मेमोरी हो। किसी एप्लिकेशन की मेमोरी मेट्रिक्स में स्पाइक के लिए यह एकदम सही नुस्खा है।
धीमी गति से रिलीज़
रूबी में मेमोरी ब्लोट का एक अन्य महत्वपूर्ण कारण सिस्टम में मुक्त मेमोरी की धीमी गति से रिलीज है। इस स्थिति में, स्मृति को उस दर से अधिक धीरे-धीरे मुक्त किया जाता है जिस पर वस्तुओं को नए स्मृति ब्लॉक आवंटित किए जाते हैं। हालांकि यह हल करने के लिए एक पारंपरिक या एक धोखेबाज़ मुद्दा नहीं है, यह स्मृति ब्लोट को तीव्रता से प्रभावित करता है - विखंडन से भी ज्यादा!
मेमोरी एलोकेटर के स्रोत की जांच करने पर, यह पता चलता है कि आवंटक को ओएस पेजों को ओएस ढेर के अंत में रिलीज करने के लिए डिज़ाइन किया गया है, और तब भी, केवल कभी-कभी ही। यह शायद प्रदर्शन कारणों से है, लेकिन यह उलटा पड़ सकता है और प्रतिकूल हो सकता है।
रूबी मेमोरी ब्लोट को कैसे ठीक करें
अब जबकि हम जानते हैं कि रूबी की मेमोरी क्यों फूल जाती है, आइए एक नज़र डालते हैं कि आप इन मुद्दों को कैसे ठीक कर सकते हैं और डीफ़्रैग्मेन्टेशन और ट्रिमिंग के माध्यम से अपने ऐप के प्रदर्शन को बेहतर बना सकते हैं।
डीफ़्रैग्मेन्टेशन के साथ रूबी मेमोरी ब्लोट को ठीक करें
कचरा संग्रह के डिजाइन के कारण विखंडन होता है, और इसे ठीक करने के लिए आप बहुत कुछ नहीं कर सकते। हालांकि, कुछ चरण हैं जिनका पालन करके आप खंडित मेमोरी डिस्क के समाप्त होने की संभावना को कम कर सकते हैं:
- यदि आप किसी ऐसी वस्तु के संदर्भ की घोषणा करते हैं जो काफी मात्रा में स्मृति का उपयोग करती है, तो सुनिश्चित करें कि जब यह काम पूरा हो जाए तो आप इसे मैन्युअल रूप से मुक्त कर दें।
- अपने सभी स्थिर ऑब्जेक्ट आवंटन को एक बड़े ब्लॉक में घोषित करने का प्रयास करें। यह आपके सभी स्थायी वर्गों, वस्तुओं और अन्य डेटा को एक ही ढेर पृष्ठों पर रखेगा। बाद में, जब आप गतिशील आवंटन के साथ खेलते हैं, तो आपको स्थिर हीप पृष्ठों के बारे में चिंता करने की आवश्यकता नहीं होगी।
- यदि संभव हो, तो शुरुआत . में बड़े गतिशील आवंटन करने का प्रयास करें आपके कोड का। यह उन्हें आपके बड़े स्थिर आवंटन मेमोरी ब्लॉक के करीब रखेगा और आपकी शेष मेमोरी को साफ रखेगा।
- यदि आप एक छोटे और दुर्लभ रूप से साफ़ किए गए कैश का उपयोग करते हैं, तो शुरुआत में इसे स्थायी स्थिर आवंटन के साथ समूहित करना बेहतर होता है। आप अपने ऐप के मेमोरी प्रबंधन को बेहतर बनाने के लिए इसे पूरी तरह से हटाने पर भी विचार कर सकते हैं।
- मानक ग्लिबक मेमोरी एलोकेटर के बजाय जेमलोक का प्रयोग करें। यह छोटा सा ट्वीक आपकी रूबी मेमोरी खपत को चार गुना तक कम कर सकता है। यहां एकमात्र चेतावनी यह है कि यह सभी परिवेशों में संगत नहीं हो सकता है, इसलिए उत्पादन शुरू करने से पहले अपने ऐप का अच्छी तरह से परीक्षण करना सुनिश्चित करें।
रूबी मेमोरी ब्लोट को ठीक करने के लिए ट्रिमिंग
धीमी मेमोरी रिलीज को ठीक करने के लिए आपको कचरा संग्रहण प्रक्रिया को ओवरराइड करने और मेमोरी को अधिक बार रिलीज़ करने की आवश्यकता होती है। एक एपीआई है जो इसे malloc_trim . नाम से कर सकती है . कचरा संग्रहण प्रक्रिया के दौरान इस फ़ंक्शन को कॉल करने के लिए आपको केवल रूबी को संशोधित करने की आवश्यकता है।
यहां संशोधित रूबी 2.6 कोड है जो malloc_trim . को कॉल करता है gc.c फ़ंक्शन में gc_start
:
gc_prof_timer_start(objspace);
{
gc_marks(objspace, do_full_mark);
// BEGIN MODIFICATION
if (do_full_mark)
{
malloc_trim(0);
}
// END MODIFICATION
}
gc_prof_timer_stop(objspace);
नोट: उत्पादन अनुप्रयोगों में इसकी अनुशंसा नहीं की जाती है क्योंकि यह आपके ऐप को अस्थिर बना सकता है। हालांकि, यह तब काम आता है जब धीमी मेमोरी रिलीज आपके प्रदर्शन के लिए बड़ी हिट का कारण बनती है, और आप किसी भी समाधान को आजमाने के लिए तैयार हैं।
रैप-अप और अगले चरण
मेमोरी ब्लोट की पहचान करना मुश्किल है और इसे ठीक करना और भी चुनौतीपूर्ण है।
इस लेख में रूबी ऐप्स में मेमोरी ब्लोट होने के दो महत्वपूर्ण कारणों पर ध्यान दिया गया - फ़्रेग्मेंटेशन और धीमी रिलीज़ - और दो सुधार:डीफ़्रैग्मेन्टेशन और ट्रिमिंग।
आने वाली ब्लोट घटना की पहचान करने के लिए आपको अपने ऐप के मेट्रिक पर लगातार नज़र रखनी चाहिए और अपने ऐप को नीचे ले जाने से पहले उसे ठीक करना चाहिए।
मुझे आशा है कि मैंने आपके रूबी एप्लिकेशन में मेमोरी ब्लोट को ठीक करने की दिशा में कुछ कदम उठाने में आपकी मदद की है।
पी.एस. यदि आप रूबी मैजिक की पोस्ट प्रेस से छूटते ही पढ़ना चाहते हैं, तो हमारे रूबी मैजिक न्यूजलेटर की सदस्यता लें और एक भी पोस्ट मिस न करें!
हमारे अतिथि लेखक कुमार हर्ष शिल्प द्वारा एक उभरते हुए सॉफ्टवेयर डेवलपर हैं। वह एक उत्साही लेखक हैं जो रूबी और जावास्क्रिप्ट जैसी लोकप्रिय वेब तकनीकों के आसपास सामग्री को एक साथ रखते हैं। आप उसकी वेबसाइट के माध्यम से उसके बारे में अधिक जानकारी प्राप्त कर सकते हैं और ट्विटर पर उसका अनुसरण कर सकते हैं।