गोलांग के साथ एप्लिकेशन विकसित करते समय, सामना की जाने वाली आम चुनौतियों में से एक मेमोरी प्रबंधन है। गोलांग दो प्राथमिक मेमोरी भंडारण स्थानों का उपयोग करता है: स्टैक और हीप। हमारे द्वारा बनाए गए एप्लिकेशन के प्रदर्शन को अनुकूलित करने के लिए यह समझना महत्वपूर्ण है कि ढेर बनाम स्टैक में एक वेरिएबल कब आवंटित किया जाता है। इस लेख में, हम उन प्रमुख स्थितियों का पता लगाएंगे जिनके कारण एक चर को ढेर में आवंटित किया जाता है और एस्केप विश्लेषण की अवधारणा पेश की जाती है, जिसका उपयोग गो कंपाइलर मेमोरी आवंटन निर्धारित करने के लिए करता है।
गोलंग में, चर को ढेर या स्टैक पर आवंटित किया जा सकता है। हीप आवंटन तब होता है जब एक वेरिएबल को फ़ंक्शन स्कोप या किसी बड़े ऑब्जेक्ट से अधिक समय तक जीवित रहने की आवश्यकता होती है। गो एस्केप विश्लेषण का उपयोग यह निर्धारित करने के लिए करता है कि ढेर पर एक वेरिएबल आवंटित किया जाना चाहिए या नहीं।
हीप आवंटन निम्नलिखित परिदृश्यों में होता है:
हीप आवंटन धीमा है क्योंकि मेमोरी का प्रबंधन गारबेज कलेक्टर (जीसी) द्वारा किया जाता है, इसलिए इसका उपयोग कम से कम करना महत्वपूर्ण है।
मुख्य विषय पर जाने से पहले, आइए स्टैक और ढेर के बीच के अंतर को समझें।
एस्केप विश्लेषण गो कंपाइलर द्वारा यह निर्धारित करने के लिए की जाने वाली एक प्रक्रिया है कि क्या एक वेरिएबल को स्टैक पर आवंटित किया जा सकता है या उसे हीप में ले जाने की आवश्यकता है। यदि कोई वेरिएबल फ़ंक्शन या दायरे से "बच" जाता है, तो इसे ढेर पर आवंटित किया जाएगा। इसके विपरीत, यदि वेरिएबल फ़ंक्शन के दायरे में रहता है, तो इसे स्टैक पर संग्रहीत किया जा सकता है।
कई स्थितियों के कारण ढेर पर चर आवंटित किए जाते हैं। आइए प्रत्येक स्थिति पर चर्चा करें।
हीप आवंटन तब होता है जब किसी फ़ंक्शन के अंदर एक वेरिएबल घोषित किया जाता है, लेकिन इसका संदर्भ फ़ंक्शन से बच जाता है। उदाहरण के लिए, जब हम किसी फ़ंक्शन से किसी स्थानीय वेरिएबल पर पॉइंटर लौटाते हैं, तो वह वेरिएबल हीप पर आवंटित किया जाएगा।
उदाहरण के लिए:
func newInt() *int { x := 42 return &x // "x" is allocated on the heap because a pointer is returned }
इस उदाहरण में, फ़ंक्शन newInt() समाप्त होने के बाद वेरिएबल x को जीवित रहना चाहिए, इसलिए गो ढेर पर x आवंटित करता है।
यदि एक वेरिएबल को उस स्थान पर संग्रहित किया जाता है जिसका जीवनचक्र उस दायरे से अधिक लंबा है जहां वेरिएबल घोषित किया गया है, तो इसे ढेर पर आवंटित किया जाएगा। एक उत्कृष्ट उदाहरण तब होता है जब एक स्थानीय चर का संदर्भ एक वैश्विक चर या एक संरचना में संग्रहीत किया जाता है जो लंबे समय तक रहता है। उदाहरण के लिए:
var global *int func setGlobal() { x := 100 global = &x // "x" is allocated on the heap because it's stored in a global variable }
यहां, वेरिएबल x को सेटग्लोबल() फ़ंक्शन से परे जीवित रहने की आवश्यकता है, इसलिए इसे ढेर पर आवंटित किया जाना चाहिए। इसी तरह, जब एक स्थानीय वैरिएबल को उस फ़ंक्शन के बाहर उपयोग की जाने वाली संरचना में रखा जाता है जहां इसे बनाया गया था, तो उस वैरिएबल को ढेर पर आवंटित किया जाएगा। उदाहरण के लिए:
type Node struct { value *int } func createNode() *Node { x := 50 return &Node{value: &x} // "x" must be on the heap because it's stored in Node }
इस उदाहरण में, चूंकि x को नोड में संग्रहीत किया जाता है और फ़ंक्शन से लौटाया जाता है, x को फ़ंक्शन से अधिक समय तक जीवित रहना चाहिए, और इस प्रकार इसे ढेर पर आवंटित किया जाता है।
कभी-कभी, बड़ी वस्तुओं, जैसे बड़े सरणी या स्लाइस के लिए ढेर आवंटन आवश्यक होता है, भले ही वस्तुएं "बच" न जाएं। ऐसा बहुत अधिक स्टैक स्थान के उपयोग से बचने के लिए किया जाता है। उदाहरण के लिए:
func largeSlice() []int { return make([]int, 1000000) // Heap allocation due to large size }
गोलंग इस बड़े टुकड़े को संग्रहित करने के लिए ढेर का उपयोग करेगा क्योंकि इसका आकार ढेर के लिए बहुत बड़ा है।
गोलांग में क्लोजर अक्सर ढेर आवंटन की ओर ले जाता है यदि क्लोजर उस फ़ंक्शन में एक स्थानीय चर का संदर्भ रखता है जहां क्लोजर को परिभाषित किया गया है। उदाहरण के लिए:
func createClosure() func() int { x := 10 return func() int { return x } // "x" must be on the heap because it's used by the closure }
चूंकि क्लोजर func() int में x का संदर्भ होता है, इसलिए x को ढेर पर आवंटित किया जाना चाहिए ताकि यह सुनिश्चित हो सके कि createClosure() फ़ंक्शन समाप्त होने के बाद भी यह जीवित रहे।
जब वेरिएबल को इंटरफ़ेस में डाला जाता है, तो गो को वेरिएबल के गतिशील प्रकार को ढेर पर संग्रहीत करने की आवश्यकता हो सकती है। ऐसा इसलिए होता है क्योंकि वेरिएबल के प्रकार के बारे में जानकारी को उसके मूल्य के साथ संग्रहीत करने की आवश्यकता होती है। उदाहरण के लिए:
func asInterface() interface{} { x := 42 return x // Heap allocation because the variable is cast to interface{} }
इस मामले में, गतिशील प्रकार की जानकारी उपलब्ध है यह सुनिश्चित करने के लिए गो ढेर पर x आवंटित करेगा।
उपरोक्त शर्तों के अलावा, कई अन्य कारक भी हैं जिनके कारण ढेर पर चर आवंटित हो सकते हैं:
गोरआउटिन के भीतर उपयोग किए जाने वाले वेरिएबल को अक्सर ढेर पर आवंटित किया जाता है क्योंकि गोरआउटिन का जीवनचक्र उस फ़ंक्शन से आगे बढ़ सकता है जिसमें इसे बनाया गया था।
यदि गो को पता चलता है कि एक वेरिएबल को गारबेज कलेक्टर (जीसी) द्वारा प्रबंधित करने की आवश्यकता है (उदाहरण के लिए, क्योंकि इसका उपयोग गोरआउट्स में किया जाता है या इसमें जटिल संदर्भ हैं), तो उस वेरिएबल को ढेर पर आवंटित किया जा सकता है।
गो अनुप्रयोगों के प्रदर्शन को अनुकूलित करने के लिए यह समझना महत्वपूर्ण है कि ढेर पर एक चर कब और क्यों आवंटित किया गया है। एस्केप विश्लेषण यह निर्धारित करने में महत्वपूर्ण भूमिका निभाता है कि क्या एक चर को स्टैक पर आवंटित किया जा सकता है या ढेर पर आवंटित किया जाना चाहिए। जबकि ढेर उन वस्तुओं को संग्रहीत करने के लिए लचीलापन प्रदान करता है जिन्हें लंबे जीवन काल की आवश्यकता होती है, ढेर के अत्यधिक उपयोग से कचरा संग्रहकर्ता का कार्यभार बढ़ सकता है और अनुप्रयोग प्रदर्शन धीमा हो सकता है। इन दिशानिर्देशों का पालन करके, आप मेमोरी को अधिक कुशलता से प्रबंधित कर सकते हैं और सुनिश्चित कर सकते हैं कि आपका एप्लिकेशन इष्टतम प्रदर्शन के साथ चलता है।
अगर आपको लगता है कि कुछ भी ऐसा है जो मुझसे छूट गया है या यदि आपके पास गो में मेमोरी प्रबंधन से संबंधित अतिरिक्त अनुभव और सुझाव हैं, तो बेझिझक उन्हें नीचे टिप्पणी में साझा करें। आगे की चर्चा हम सभी को इस विषय को बेहतर ढंग से समझने और अधिक कुशल कोडिंग प्रथाओं को विकसित करने में मदद कर सकती है।
अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।
Copyright© 2022 湘ICP备2022001581号-3