जावास्क्रिप्ट कचरा संग्रह क्या है? बेहतर कोड लिखने के लिए एक वेब प्रोग्रामर के लिए जावास्क्रिप्ट कचरा संग्रहण के बारे में समझना क्या महत्वपूर्ण है?
जावास्क्रिप्ट कचरा संग्रह क्या है? बेहतर कोड लिखने के लिए एक वेब प्रोग्रामर के लिए जावास्क्रिप्ट कचरा संग्रहण के बारे में समझना क्या महत्वपूर्ण है?
जवाबों:
एरिक लिपर्ट ने कुछ समय पहले इस विषय के बारे में एक विस्तृत ब्लॉग पोस्ट लिखा था (इसके अलावा इसकी तुलना VBScript से की गई थी )। अधिक सटीक रूप से, उन्होंने JScript के बारे में लिखा , जो कि Microsoft का ECMAScript का कार्यान्वयन है, हालांकि जावास्क्रिप्ट के समान है। मुझे लगता है कि आप इंटरनेट एक्सप्लोरर के जावास्क्रिप्ट इंजन के लिए व्यवहार के विशाल बहुमत के समान होगा मान सकते हैं। बेशक, कार्यान्वयन ब्राउज़र से ब्राउज़र तक भिन्न होगा, हालांकि मुझे संदेह है कि आप कई सामान्य सिद्धांतों को ले सकते हैं और उन्हें अन्य ब्राउज़रों पर लागू कर सकते हैं।
उस पृष्ठ से उद्धृत:
JScript एक नोजेनरेशनल मार्क-एंड-स्वीप कचरा कलेक्टर का उपयोग करता है। यह इस तरह काम करता है:
प्रत्येक चर जो "स्कोप" है, उसे "मेहतर" कहा जाता है। एक मेहतर एक संख्या, एक वस्तु, एक स्ट्रिंग, जो भी हो, को संदर्भित कर सकता है। हम मैला ढोने वालों की एक सूची बनाए रखते हैं - जब वे स्कोप सूची में आते हैं तो वे स्कोव सूची में चले जाते हैं और जब वे स्कोप सूची से बाहर निकलते हैं तो वे स्कोप की सूची में चले जाते हैं।
हर अब और फिर कचरा कलेक्टर चलाता है। पहले यह हर वस्तु, चर, स्ट्रिंग, आदि पर एक "चिह्न" डालता है - जीसी द्वारा ट्रैक की गई सभी मेमोरी। (JScript आंतरिक डेटा संरचना का आंतरिक रूप से उपयोग करता है और उस संरचना में बहुत सारे अतिरिक्त अप्रयुक्त बिट्स हैं, इसलिए हम उनमें से एक सेट करते हैं।)
दूसरा, यह मेहतरों पर निशान साफ करता है और मेहतर संदर्भों का सकर्मक समापन है। इसलिए यदि एक मेहतर वस्तु एक निरर्थक वस्तु का संदर्भ देती है तो हम उस बकवास को स्पष्ट करते हैं, और वह सब कुछ जिस पर वह संदर्भित है। (मैं अपने पहले के पोस्ट की तुलना में "बंद" शब्द का एक अलग अर्थ में उपयोग कर रहा हूं।)
इस बिंदु पर हम जानते हैं कि अभी भी चिह्नित की गई सभी मेमोरी को मेमोरी आवंटित की जाती है, जो किसी भी-स्कोप वैरिएबल से किसी भी रास्ते से नहीं पहुंच सकती है। उन सभी वस्तुओं को अपने आप को फाड़ने का निर्देश दिया जाता है, जो किसी भी परिपत्र संदर्भ को नष्ट कर देता है।
कचरा संग्रहण का मुख्य उद्देश्य प्रोग्रामर को उन वस्तुओं के मेमोरी प्रबंधन के बारे में चिंता न करने की अनुमति देना है जो वे बनाते हैं और उपयोग करते हैं, हालांकि निश्चित रूप से इसे कभी-कभी कोई परहेज नहीं है - कचरा संग्रह कैसे काम करता है इसका कम से कम एक मोटा विचार रखना हमेशा फायदेमंद होता है ।
ऐतिहासिक नोट: उत्तर के पहले संशोधन में delete
ऑपरेटर के लिए एक गलत संदर्भ था । जावास्क्रिप्ट में delete
ऑपरेटर एक ऑब्जेक्ट से एक संपत्ति निकालता है , और delete
सी / सी ++ में पूरी तरह से अलग है ।
delete
गलत तरीके से उपयोग करता है; उदाहरण के लिए, इसके बजाय delete foo
, आपको पहले इवेंट श्रोता को इसके माध्यम से निकालना चाहिए window.removeEventListener()
और फिर foo = null
चर को अधिलेखित करने के लिए उपयोग करना चाहिए ; IE में, delete window.foo
(लेकिन नहीं delete foo
) भी काम किया होता अगर foo
वैश्विक होता, लेकिन फिर भी यह FF या ओपेरा में नहीं होता
delete
एक अपरेटिव ऑपरेटर (एक अभिव्यक्ति) है, न कि एक स्टेटमेंट (यानी:) delete 0, delete 0, delete 3
। अभिव्यक्ति कथन द्वारा व्यक्त किए जाने पर यह कथन जैसा लगता है।
DOM ऑब्जेक्ट्स शामिल होने पर परिपत्र संदर्भों से सावधान रहें:
जावास्क्रिप्ट में मेमोरी लीक पैटर्न
ध्यान रखें कि स्मृति को केवल तभी पुनः प्राप्त किया जा सकता है जब ऑब्जेक्ट में कोई सक्रिय संदर्भ न हों। यह क्लोजर और इवेंट हैंडलर के साथ एक आम नुकसान है, क्योंकि कुछ जेएस इंजन यह जांच नहीं करेंगे कि कौन से चर वास्तव में आंतरिक कार्यों में संदर्भित हैं और बस एन्कोडिंग कार्यों के सभी स्थानीय चर रखें।
यहाँ एक सरल उदाहरण दिया गया है:
function init() {
var bigString = new Array(1000).join('xxx');
var foo = document.getElementById('foo');
foo.onclick = function() {
// this might create a closure over `bigString`,
// even if `bigString` isn't referenced anywhere!
};
}
bigString
जब तक घटना हैंडलर के आसपास न हो, एक भोले जेएस कार्यान्वयन लागू नहीं हो सकता । इस समस्या को हल करने के कई तरीके हैं, उदाहरण bigString = null
के लिए init()
( delete
स्थानीय चर और फ़ंक्शन तर्क के लिए काम नहीं करेगा) सेटिंग : delete
ऑब्जेक्ट से गुण हटाता है, और चर ऑब्जेक्ट दुर्गम है - सख्त मोड में ES5 भी ReferenceError
अगर आप कोशिश करेंगे तो फेंक देंगे एक स्थानीय चर को नष्ट करने के लिए!)।
यदि आप स्मृति खपत के लिए परवाह करते हैं तो मैं अनावश्यक बंद से बचने की सलाह देता हूं।
ब्लॉग से लिया गया अच्छा उद्धरण
DOM घटक "कचरा एकत्र" है, जैसा कि JScript घटक है, जिसका अर्थ है कि यदि आप या तो घटक के भीतर एक ऑब्जेक्ट बनाते हैं, और फिर उस ऑब्जेक्ट का ट्रैक खो देते हैं, तो यह अंततः साफ हो जाएगा।
उदाहरण के लिए:
function makeABigObject() {
var bigArray = new Array(20000);
}
जब आप उस फ़ंक्शन को कॉल करते हैं, तो JScript घटक एक ऑब्जेक्ट (bigArray नाम) बनाता है जो फ़ंक्शन के भीतर पहुंच योग्य है। जैसे ही फ़ंक्शन वापस आता है, हालांकि, आप bigArray का "ट्रैक खो देते हैं" क्योंकि अब इसे संदर्भित करने का कोई तरीका नहीं है। ठीक है, JScript घटक को पता चलता है कि आपने इसका ट्रैक खो दिया है, और इसलिए BigArray को साफ किया जाता है - इसकी मेमोरी पुनः प्राप्त होती है। DOM कंपोनेंट में एक ही तरह की चीज काम करती है। यदि आप कहते हैं document.createElement('div')
, या कुछ समान है, तो DOM घटक आपके लिए एक ऑब्जेक्ट बनाता है। एक बार जब आप किसी तरह उस वस्तु का ट्रैक खो देते हैं, तो DOM घटक संबंधित को साफ कर देगा।
मेरे ज्ञान का सबसे अच्छा करने के लिए, जावास्क्रिप्ट की वस्तुओं को समय-समय पर कचरा एकत्र किया जाता है जब ऑब्जेक्ट के लिए कोई संदर्भ शेष नहीं होता है। यह कुछ ऐसा है जो स्वचालित रूप से होता है, लेकिन यदि आप यह देखना चाहते हैं कि यह C ++ स्तर पर कैसे काम करता है, तो यह WebKit या V8 स्रोत कोड पर एक नज़र डालने के लिए समझ में आता है
आमतौर पर आपको इसके बारे में सोचने की ज़रूरत नहीं है, हालांकि, पुराने ब्राउज़रों में, जैसे IE 5.5 और IE 6 के शुरुआती संस्करण, और शायद वर्तमान संस्करण, क्लोज़र परिपत्र संदर्भ बनाएंगे, जब अनियंत्रित मेमोरी को खा जाएगा। उस विशेष मामले में जिसका मतलब है कि मैं क्लोज़र के बारे में हूं, यह तब था जब आपने एक डोम ऑब्जेक्ट में जावास्क्रिप्ट संदर्भ जोड़ा था, और डोम ऑब्जेक्ट पर एक ऑब्जेक्ट जिसे जावास्क्रिप्ट ऑब्जेक्ट पर वापस भेजा गया था। मूल रूप से इसे कभी भी एकत्र नहीं किया जा सकता है, और अंततः ओएस का परीक्षण करने वाले ऐप्स में अस्थिर होने का कारण होगा जो क्रैश बनाने के लिए लूप किए गए थे। व्यवहार में ये लीक आमतौर पर छोटे होते हैं, लेकिन अपने कोड को साफ रखने के लिए आपको जावास्क्रिप्ट ऑब्जेक्ट को DOM ऑब्जेक्ट पर डिलीट करना चाहिए।
आमतौर पर JSON डेटा जैसी बड़ी वस्तुओं को तुरंत डिलीट करने के लिए डिलीट कीवर्ड का उपयोग करना एक अच्छा विचार है जो आपको वापस मिल गया है और इसके साथ जो भी करने की आवश्यकता है, विशेष रूप से मोबाइल वेब विकास में। यह GC के अगले स्वीप के कारण उस वस्तु को हटा देता है और उसकी मेमोरी को मुक्त कर देता है।
mark-and-sweep
स्टाइल के एल्गोरिदम इसका ध्यान रखते हैं ।
कचरा संग्रह (जीसी) उन वस्तुओं को हटाकर स्वचालित मेमोरी प्रबंधन का एक रूप है जिनकी अब कोई आवश्यकता नहीं है।
मेमोरी के साथ कोई भी प्रक्रिया सौदा इन चरणों का पालन करें:
1 - आप की जरूरत है अपनी स्मृति स्थान आवंटित करें
2 - कुछ प्रसंस्करण करते हैं
3 - इस मेमोरी स्पेस को फ्री करें
वहाँ दो मुख्य एल्गोरिथ्म का पता लगाने के लिए उपयोग किया जाता है जो वस्तुओं की अब कोई आवश्यकता नहीं है।
संदर्भ-गणना कचरा संग्रह : यह एल्गोरिथ्म "एक वस्तु की अब और आवश्यकता नहीं है" की परिभाषा को कम कर देता है "किसी वस्तु को इसके संदर्भ में कोई अन्य वस्तु नहीं है", वस्तु को हटा दिया जाएगा यदि कोई संदर्भ बिंदु नहीं है
मार्क-एंड-स्वीप एल्गोरिथ्म : प्रत्येक ऑब्जेक्ट को रूट सोर्स से कनेक्ट करें। कोई भी वस्तु जड़ या अन्य वस्तु से नहीं जुड़ती है। यह ऑब्जेक्ट हटा दिया जाएगा।
वर्तमान में अधिकांश आधुनिक ब्राउज़र दूसरे एल्गोरिथ्म का उपयोग कर रहे हैं।
"कंप्यूटर विज्ञान में, कचरा संग्रह (जीसी) स्वचालित मेमोरी प्रबंधन का एक रूप है। कचरा संग्रहकर्ता, या सिर्फ कलेक्टर, कचरे को पुनः प्राप्त करने का प्रयास करता है, या उन वस्तुओं द्वारा उपयोग की जाने वाली मेमोरी जो कभी भी एप्लिकेशन द्वारा एक्सेस या म्यूट नहीं किया जाएगा।"
सभी जावास्क्रिप्ट इंजन के पास अपने स्वयं के कचरा संग्रहकर्ता होते हैं, और वे भिन्न हो सकते हैं। ज्यादातर समय आपको उनसे निपटना नहीं पड़ता क्योंकि वे वही करते हैं जो वे करने वाले थे।
बेहतर कोड लिखना ज्यादातर इस बात पर निर्भर करता है कि आप प्रोग्रामिंग सिद्धांतों, भाषा और विशेष रूप से कार्यान्वयन को कितना अच्छा जानते हैं।
जावास्क्रिप्ट कचरा संग्रह क्या है?
जाँच इस
बेहतर कोड लिखने के लिए एक वेब प्रोग्रामर के लिए जावास्क्रिप्ट कचरा संग्रहण के बारे में समझना क्या महत्वपूर्ण है?
जावास्क्रिप्ट में आप मेमोरी आवंटन और डील्लोकेशन के बारे में परवाह नहीं करते हैं। संपूर्ण समस्या को जावास्क्रिप्ट इंटरप्रेटर की मांग की जाती है। जावास्क्रिप्ट में अभी भी लीक संभव है, लेकिन वे दुभाषिया के कीड़े हैं। यदि आप इस विषय में रुचि रखते हैं तो आप www.memorymanagement.org पर अधिक पढ़ सकते हैं
खिड़कियों पर आप Drip.exe का उपयोग कर सकते हैं स्मृति लीक खोजने के लिए या जांचें कि क्या आपके मुफ्त मेम दिनचर्या काम करती है।
यह वास्तव में सरल है, बस एक वेबसाइट URL दर्ज करें और आप एकीकृत IE रेंडरर की मेमोरी खपत देखेंगे। फिर ताज़ा करें, यदि मेमोरी बढ़ती है, तो आपको वेबपेज पर कहीं स्मृति रिसाव मिला। लेकिन यह देखने के लिए भी बहुत उपयोगी है कि क्या IE के लिए मेमोरी काम को मुक्त करने के लिए दिनचर्या।
संदर्भ प्रकार ऑब्जेक्ट को सीधे उस चर में संग्रहीत नहीं करता है जिसे इसे सौंपा गया है, इसलिए इस उदाहरण में ऑब्जेक्ट चर वास्तव में ऑब्जेक्ट उदाहरण में नहीं है। इसके बजाय, यह मेमोरी में उस स्थान पर एक पॉइंटर (या संदर्भ) रखता है जहां ऑब्जेक्ट मौजूद है
var object = new Object();
यदि आप एक चर दूसरे को सौंपते हैं, तो प्रत्येक चर सूचक की एक प्रति प्राप्त करता है, और दोनों अभी भी स्मृति में एक ही वस्तु को संदर्भित करते हैं।
var object1 = new Object();
var object2 = object1;
जावास्क्रिप्ट एक कचरा एकत्र करने वाली भाषा है, इसलिए जब आप संदर्भ प्रकारों का उपयोग करते हैं, तो आपको स्मृति आवंटन के बारे में चिंता करने की आवश्यकता नहीं है। हालाँकि, यह उन वस्तुओं को हटाने के लिए सबसे अच्छा है जिनकी आपको अब आवश्यकता नहीं है ताकि कचरा संग्रहकर्ता उस मेमोरी को मुक्त कर सके। ऐसा करने का सबसे अच्छा तरीका ऑब्जेक्ट चर को शून्य पर सेट करना है।
var object1 = new Object();
// do something
object1 = null; // dereference
डेरीफेरिंग ऑब्जेक्ट विशेष रूप से बहुत बड़े अनुप्रयोगों में महत्वपूर्ण है जो लाखों ऑब्जेक्ट का उपयोग करते हैं।
ऑब्जेक्ट ओरिएंटेड जावास्क्रिप्ट के सिद्धांतों से - निकोलस सी। ज़कास