जब भी आप अपना कोड चलाते हैं, आप मेमोरी का उपयोग करते हैं। जब आप Ruby जैसी भाषा में लिखते हैं, तो ऐसा लगता है कि आपके लिए उपलब्ध मेमोरी अनंत है। आप बिना उस सिस्टम की निश्चित मात्रा के बारे में सोचे चलते रह सकते हैं जो आपके कोड को चला रहा है। इस Ruby Magic एपिसोड में हम बताएंगे कि यह कैसे काम करता है!
थोड़ा इतिहास
वापस उन दिनों में, Ruby जैसी स्क्रिप्टिंग भाषाएं अभी तक मौजूद नहीं थीं। लोग केवल C जैसी भाषाओं में कोड लिखते थे, एक निम्न-स्तरीय प्रोग्रामिंग भाषा। इन भाषाओं को निम्न-स्तरीय बनाने वाली चीजों में से एक यह है कि आपको अपने बाद सफाई करनी होती है। उदाहरण के लिए, जब भी आप एक String को स्टोर करने के लिए मेमोरी आवंटित करते हैं, तो आपको यह भी तय करना होता है कि इसे कब साफ करना है।
मैन्युअल सफाई
यह कुछ नकली Ruby कोड जैसा दिखता है। यह एक वेरिएबल घोषित करता है और हमारे द्वारा उपयोग की गई मेमोरी को साफ करने के लिए free मेथड का उपयोग करता है—यह मेथड वास्तव में Ruby में मौजूद नहीं है—उसके बाद जब हम वेरिएबल के साथ हो जाते हैं।
1_000_000.times do |i|
variable = "Variable #{i}"
puts variable
free(variable)
end
प्रोग्रामिंग का एक थकाऊ तरीका
आपने शायद पहले ही महसूस कर लिया है कि यहां एक जोखिम है: क्या होगा यदि आप वेरिएबल को free करना भूल जाते हैं? उस स्थिति में उस वेरिएबल की सामग्री बस तब तक मेमोरी में पड़ी रहेगी जब तक प्रोसेस बाहर नहीं निकल जाता। यदि आप इसे अक्सर पर्याप्त करते हैं, तो आप मेमोरी से बाहर हो जाएंगे और आपका प्रोसेस क्रैश हो जाएगा।
अगला उदाहरण एक और आम मुद्दा दर्शाता है:
1_000_000.times do |i|
variable = "Variable #{i}"
free(variable)
puts variable
end
हम वेरिएबल घोषित करते हैं और इसे free करते हैं। लेकिन फिर हम इसका फिर से उपयोग करने की कोशिश करते हैं, जो असंभव है क्योंकि यह अब मौजूद नहीं है। यदि यह C होता, तो आपका प्रोग्राम अब segfault के साथ क्रैश हो जाता। ऊप्स!
इंसान गलती करने वाली मशीनें हैं
इंसान हर समय इस तरह की गलतियाँ न करने के लिए कुख्यात रूप से खराब हैं। इसलिए मेमोरी को स्वचालित रूप से साफ करने के तरीके की आवश्यकता है। ऐसा करने का सबसे लोकप्रिय तरीका—Ruby में भी उपयोग किया जाता है—गारबेज कलेक्शन (GC) है।
गारबेज कलेक्शन (GC) कैसे काम करता है
GC का उपयोग करने वाली भाषा में, आप ऑब्जेक्ट्स बना सकते हैं बिना उन्हें मैन्युअल रूप से साफ किए। जब भी आप एक ऑब्जेक्ट बनाते हैं, यह गारबेज कलेक्टर के साथ रजिस्टर हो जाता है। GC आपके द्वारा इस ऑब्जेक्ट के लिए बनाए गए सभी संदर्भों को ट्रैक करने की कोशिश करता है। जब यह निर्धारित करता है कि आप अब ऑब्जेक्ट का उपयोग नहीं कर रहे हैं, तो इसे सफाई के लिए मार्क किया जाता है। हर बार एक समय में गारबेज कलेक्टर आपके प्रोग्राम को रोकता है और सभी मार्क की गई ऑब्जेक्ट्स को साफ करता है।
कुछ उदाहरणों को देखना
हमारे द्वारा पहले उपयोग किए गए सरल लूप में GC का काम काफी आसान है। लूप के प्रत्येक पुनरावृत्ति के साथ, वेरिएबल का उपयोग अब कहीं भी नहीं किया जाता है। वेरिएबल को तुरंत सफाई के लिए मार्क किया जा सकता है।
1_000_000.times do |i|
variable = "Variable #{i}"
puts variable
end
अगले उदाहरण में हम वेरिएबल को puts_later मेथड में पास करते हैं जो 30 सेकंड इंतजार करता है और फिर वेरिएबल को puts करता है।
def puts_later(variable)
Thread.new do
sleep 30
puts variable
end
end
1_000_000.times do |i|
variable = "Variable #{i}"
puts_later variable
end
गारबेज कलेक्टर का काम इस अपेक्षाकृत सरल उदाहरण में पहले से ही काफी जटिल है। उसे यह समझना होगा कि हम puts_later मेथड में वेरिएबल को संदर्भित करते हैं। क्योंकि मेथड एक थ्रेड शुरू करता है, गारबेज कलेक्टर को थ्रेड को ट्रैक करना होगा और इसके समाप्त होने का इंतजार करना होगा। केवल तभी वेरिएबल को सफाई के लिए मार्क किया जा सकता है।
जब यह जटिल हो जाता है
जटिल उदाहरणों में जाए बिना, मुझ पर विश्वास करें जब मैं कहता हूं कि गारबेज कलेक्टर का काम वास्तव में कठिन है। यह यह भी बताता है कि GC आपके प्रोडक्शन वातावरण में ओवरहेड और समस्याएं क्यों पैदा कर सकता है। इसे आपके प्रोग्राम में क्या हो रहा है इसकी बहुत विस्तृत समझ होनी चाहिए ताकि मेमोरी को ठीक से साफ किया जा सके, जिसे सही करने में काफी CPU साइकिल लगती हैं। लेकिन हे, यह खुद सफाई करने से बेहतर है!
गारबेज कलेक्शन में और भी बहुत कुछ है
यह केवल गारबेज कलेक्शन का हमारा परिचय था। भविष्य के लेख में हम देखेंगे कि यह वास्तव में Ruby में कैसे काम करता है, और कैसे आप GC को माप और ट्यून करके अपने एप्लिकेशन के प्रदर्शन में सुधार कर सकते हैं।
अपडेट: अगला एपिसोड यहां उपलब्ध है।