कचरे के ढेर स्टैक ओवरफ्लो से कैसे बचें?


23

इसलिए मैं इस बारे में सोच रहा था कि कचरा उठाने वाले कैसे काम करते हैं और मैंने एक दिलचस्प मुद्दा सोचा। संभवतः कचरे के संग्रहकर्ताओं को सभी संरचनाओं को एक ही तरह से पार करना पड़ता है। वे मौसम को नहीं जान सकते हैं कि वे एक लिंक की गई सूची या एक संतुलित पेड़ या जो कुछ भी कर रहे हैं। वे अपनी खोज में बहुत अधिक मेमोरी का उपयोग नहीं कर सकते हैं। एक संभव तरीका है, और एक ही रास्ता है कि मैं सभी संरचनाओं को पार करने के लिए सोच सकता हूं, हो सकता है कि उन सभी को फिर से पार करने के लिए जिस तरह से आप एक द्विआधारी पेड़ हो। हालांकि यह एक लिंक की गई सूची पर एक स्टैक ओवरफ्लो या यहां तक ​​कि एक खराब संतुलित बाइनरी ट्री देगा। लेकिन सभी कचरा एकत्र करने वाली भाषाएं जो मैंने कभी इस्तेमाल की हैं, ऐसे मामलों से निपटने में कोई समस्या नहीं है।

ड्रैगन बुक में यह एक "Unscanned" कतार का उपयोग करता है। मूल रूप से संरचना को पुनरावृत्ति करने के बजाय यह केवल उन चीजों को जोड़ता है जिन्हें एक कतार के रूप में चिह्नित करने की आवश्यकता होती है और फिर अंत में चिह्नित नहीं की गई प्रत्येक चीज़ के लिए इसे हटा दिया जाता है। लेकिन क्या यह कतार बहुत बड़ी नहीं होगी?

तो, कचरा संग्रहकर्ता मनमानी संरचनाओं को कैसे पार करते हैं? यह ट्रैवर्सल तकनीक ओवरफ्लो से कैसे बचती है?


1
जीसी ने सभी संरचनाओं को कमोबेश उसी तरह से पार किया, लेकिन केवल बहुत ही सार अर्थ में (उत्तर देखें)। जिस तरह से वे चीज़ों पर नज़र रखते हैं, वह बहुत अधिक परिष्कृत है, जो प्राथमिक प्रस्तुतियों द्वारा आप पाठ्यपुस्तकों में पा सकते हैं। और वे पुनरावृत्ति का उपयोग नहीं करते हैं। इसके अलावा, वर्चुअल मेमोरी के साथ, खराब कार्यान्वयन जीसी मंदी के रूप में दिखाते हैं, शायद ही कभी स्मृति अतिप्रवाह के रूप में।
बबौ

आप ट्रेसिंग के लिए आवश्यक स्थान की चिंता करते हैं। लेकिन स्मृति को भेद करने के लिए आवश्यक स्थान या संरचनाओं के बारे में क्या पता लगाया गया है और इसका उपयोग स्मृति से किया जा सकता है, जो संभावित रूप से प्रशंसनीय है। यह एक महत्वपूर्ण स्मृति लागत हो सकती है, संभवतः ढेर आकार के आनुपातिक।
बबौ

मुझे लगा कि यह 16 या उससे अधिक बड़े ऑब्जेक्ट के आकार के बिटवेक्टर के साथ किया जाएगा ताकि ओवर हेड न्यूनतम 1000 गुना कम हो।
जेक

इसे करने के कई तरीके हैं (उत्तर देखें), और उनका उपयोग ट्रेसिंग के लिए भी किया जा सकता है, जो तब आपके प्रश्न का उत्तर देगा (बिटवेक्टर या बिटमैप का उपयोग ट्रेसिंग या आपके द्वारा सुझाए गए कतार के बजाय ट्रेसिंग के लिए किया जा सकता है)। आप सभी वस्तुओं को बड़ा नहीं मान सकते हैं, जब तक कि आप छोटी वस्तुओं पर जगह बर्बाद करने का इरादा नहीं रखते हैं, जिनमें से कई हो सकते हैं, और फिर आपको अंतरिक्ष के लिए चिंता नहीं करनी चाहिए। यदि आप वर्चुअल मेमोरी में हैं, तो स्पेस अक्सर बहुत कम होता है और समस्याएं बहुत अलग होती हैं।
बबौ

जवाबों:


13

ध्यान दें कि मैं कचरा संग्रहण विशेषज्ञ नहीं हूं। यह उत्तर केवल तकनीकों का उदाहरण देता है। मैं यह दावा नहीं करता कि यह कचरा संग्रहण तकनीकों का प्रतिनिधि अवलोकन है।

एक असुरक्षित कतार एक आम विकल्प है। कतार बड़ी हो सकती है - संभवतः सबसे बड़ी डेटा संरचना जितनी बड़ी हो सकती है। कतार आमतौर पर स्पष्ट रूप से संग्रहीत की जाती है, कचरा संग्रह धागे के ढेर पर नहीं।

एक बार जब एक नोड के सभी बच्चों को स्कैन किया गया है, तो नोड को असंबद्ध कतार से हटाया जा सकता है। यह मूल रूप से एक टेल कॉल ऑप्टिमाइज़ेशन है। कचरा इकट्ठा करने वालों में पिछले नोड के सबसे गहरे बच्चे को स्कैन करने के प्रयास में शामिल हो सकते हैं; उदाहरण के लिए लिस्प के लिए एक जीसी पहले carएक consसे पहले स्कैन करना चाहिए cdr

एक असुरक्षित कतार में रखने से बचने का एक तरीका यह है कि जगह-जगह पॉइंटर्स को संशोधित किया जाए, जिससे बच्चा अस्थायी रूप से अभिभावक को इंगित कर सके। यह एक निरंतर-मेमोरी ट्री ट्रैवर्सल तकनीक है जिसका उपयोग कचरा संग्रहकर्ताओं के अलावा अन्य संदर्भों में किया जाता है। इस तकनीक का नकारात्मक पक्ष यह है कि जब जीसी एक डेटा संरचना का पता लगा रहा है, तो डेटा संरचना अमान्य है, इसलिए जीसी को दुनिया को रोकना होगा। यह एक सौदा ब्रेकर नहीं है: कई कचरा कलेक्टरों में एक ऐसा चरण शामिल होता है जो चरणों के अलावा, दुनिया को रोकता है, लेकिन इसके परिणामस्वरूप कचरा नहीं छोड़ सकता है।


2
अंतिम पैराग्राफ में वर्णित तकनीक को अक्सर " पॉइंटर रिवर्सल " कहा जाता है ।
भटकना तर्क

@AnderingLogic हाँ, पॉइंटर रिवर्सल यह है कि मैंने इसे अपने उत्तर में कैसे बुलाया। यह Deutsch, Schorr और Waite (1967) के कारण है। हालांकि, यह गलत है कि यह निरंतर मेमोरी में काम करता है: इसमें p पॉइंटर्स के साथ प्रत्येक सेल के लिए p log 2 p bits अतिरिक्त बिट्स की आवश्यकता होती है , हालांकि बिट स्टैक्स का उपयोग करके इसे कम किया जा सकता है। आपके द्वारा स्वीकार किए गए उत्तर को काफी सही या समान कारण से पूरा नहीं किया गया है। log2pp
बबौ

मैं है इन अतिरिक्त बिट्स की जरूरत के बिना एक कस्टम जीसी में सूचक उलट इस्तेमाल किया; चाल के लिए स्मृति में वस्तुओं के एक विशेष-इन-मेमोरी प्रतिनिधित्व का उपयोग करना था। अर्थात्, ऑब्जेक्ट "हेडर" बीच में था, हेडर से पहले पॉइंटर फ़ील्ड और उसके बाद नॉन-पॉइंटर फ़ील्ड; इसके अलावा, सभी पॉइंटर्स संरेखित किए गए थे, और हेडर में कम से कम महत्वपूर्ण बिट हमेशा सेट के साथ एक फ़ील्ड शामिल था। इस प्रकार, पॉइंटर रिवर्सल बैकट्रैक के दौरान, अगले पॉइंटर तक पहुंचना और हम किसी वस्तु के साथ समाप्त हो गए थे, अतिरिक्त बिट्स के बिना स्पष्ट रूप से किया जा सकता है। इस लेआउट ने OOP विरासत का भी समर्थन किया।
थॉमस पोर्निन

@ थोमसपोकिन मुझे लगता है कि थोड़ी जानकारी कहीं होनी चाहिए। सवाल यह है कि कहां है? क्या हम चैट में इस पर चर्चा कर सकते हैं? मुझे अब छोड़ना होगा, लेकिन मैं इस बात की तह तक जाना चाहूंगा। या वेब पर एक विवरण उपलब्ध है?
बबौ

1
@ बाबू और थॉमस कृपया
गिलेस

11

संक्षेप में : कचरा संग्रहकर्ता पुनरावृत्ति का उपयोग नहीं करते हैं। वे अनिवार्य रूप से दो सेट (जो गठबंधन कर सकते हैं) का ट्रैक रखकर ट्रेसिंग को नियंत्रित करते हैं। अनुरेखण और सेल प्रसंस्करण का क्रम अप्रासंगिक है, जो सेटों का प्रतिनिधित्व करने के लिए काफी कार्यान्वयन स्वतंत्रता देता है। इसलिए कई समाधान हैं जो वास्तव में स्मृति उपयोग में बहुत सस्ते हैं। यह आवश्यक है क्योंकि जीसी ठीक कहा जाता है जब ढेर स्मृति से बाहर चलाता है। बड़े आभासी यादों के साथ चीजें थोड़ी भिन्न होती हैं, क्योंकि नए पृष्ठों को आसानी से आवंटित किया जा सकता है, और दुश्मन को जगह की कमी नहीं है, लेकिन डेटा इलाके की कमी है

मुझे लगता है कि आप कचरा संग्रहकर्ता का पता लगाने पर विचार कर रहे हैं , न कि संदर्भ गणना जिसके लिए आपका प्रश्न लागू नहीं होता है।

UV

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

  • VVV=UT

  • U

  • T

  • H

VUUT

UV

UcVUcUT

UUV=TVHVV

VUUT

मैं इस बात का भी विवरण छोड़ देता हूं कि एक सेल क्या है, चाहे वे एक आकार में हों या कई, हम उनमें पॉइंटर्स कैसे ढूंढते हैं, उन्हें कैसे कॉम्पैक्ट किया जा सकता है, और अन्य तकनीकी मुद्दों के एक मेजबान जो आप कचरा संग्रह पर पुस्तकों और सर्वेक्षणों में पा सकते हैं ।

U

जहां ज्ञात कार्यान्वयन अलग-अलग हैं, जहां ये सेट वास्तव में प्रतिनिधित्व करते हैं। कई तकनीकों का वास्तव में उपयोग किया गया है:

  • बिट मैप: कुछ मेमोरी स्पेस एक मैप के लिए संरक्षित होता है, जिसमें प्रत्येक मेमोरी सेल के लिए एक बिट होता है, जिसे सेल के एड्रेस का उपयोग करके पाया जा सकता है। बिट तब होता है जब संबंधित सेल मानचित्र द्वारा परिभाषित सेट में होता है। यदि केवल बिट मैप्स का उपयोग किया जाता है, तो आपको प्रति सेल केवल 2 बिट्स की आवश्यकता है।

  • वैकल्पिक रूप से, आपके पास इसे चिह्नित करने के लिए प्रत्येक कक्ष में एक विशेष टैग बिट (या 2) के लिए स्थान हो सकता है।

  • log2pp

  • आप सेल की सामग्री और उसके संकेत पर एक विधेय का परीक्षण कर सकते हैं।

  • आप केवल सेट की गई सेल से संबंधित सभी कक्षों के लिए इच्छित मेमोरी के एक नि: शुल्क भाग में सेल को स्थानांतरित कर सकते हैं।

  • VTTU

  • आप वास्तव में इन तकनीकों को जोड़ सकते हैं, यहां तक ​​कि एक सेट के लिए भी।

जैसा कि कहा गया है, उपरोक्त सभी का उपयोग कुछ कार्यान्वित कचरा कलेक्टर द्वारा किया गया है, कुछ के रूप में अजीब लग सकता है। यह सब कार्यान्वयन की विभिन्न बाधाओं पर निर्भर करता है। और वे स्मृति उपयोग में सस्ते हो सकते हैं, संभवतः प्रसंस्करण नीतियों द्वारा मदद की जा सकती है जो कि उस उद्देश्य के लिए स्वतंत्र रूप से चुनी जा सकती हैं, क्योंकि वे अंतिम परिणाम के लिए मायने नहीं रखते हैं।

एक नए क्षेत्र में कोशिकाओं को स्थानांतरित करने वाला सबसे अजीब लग सकता है, वास्तव में बहुत आम है: इसे प्रतिलिपि संग्रह कहा जाता है। इसका उपयोग ज्यादातर वर्चुअल मेमोरी के साथ किया जाता है।

स्पष्ट रूप से कोई पुनरावृत्ति नहीं है, और उत्परिवर्ती एल्गोरिथ्म स्टैक का उपयोग करने की आवश्यकता नहीं है।

एक और महत्वपूर्ण बिंदु यह है कि बड़ी आभासी यादों के लिए कई आधुनिक जीसी लागू किए जाते हैं । फिर लागू करने के लिए जगह और अतिरिक्त सूची या स्टैक एक मुद्दा नहीं है क्योंकि नए पृष्ठों को आसानी से आवंटित किया जा सकता है। हालांकि, बड़ी आभासी यादों में, शत्रु स्थान की कमी नहीं है , बल्कि स्थानीयता की कमी है । फिर, सेट का प्रतिनिधित्व करने वाली संरचना, और उनका उपयोग, डेटा संरचना और जीसी निष्पादन की स्थानीयता को संरक्षित करने की दिशा में सक्षम होना चाहिए । समस्या अंतरिक्ष नहीं बल्कि समय है। अपर्याप्त कार्यान्वयन मेमोरी ओवरफ़्लो की तुलना में अस्वीकार्य मंदी दिखाने की अधिक संभावना है।

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


4

स्टैक ओवरफ्लो से बचने का मानक तरीका एक स्पष्ट स्टैक (ढेर में एक डेटा संरचना के रूप में संग्रहीत) का उपयोग करना है। इन उद्देश्यों के लिए भी काम करता है। कचरा बीनने वालों के पास अक्सर उन वस्तुओं की एक कार्यसूची होती है, जिनकी जांच / पता लगाने की आवश्यकता होती है, जो इस भूमिका को निभाती है। उदाहरण के लिए, आपकी "Unscanned" कतार इस तरह के पैटर्न का एक उदाहरण है। कतार संभावित रूप से बड़ी हो सकती है, लेकिन यह स्टैक ओवरफ्लो का कारण नहीं बनती है, क्योंकि यह स्टैक सेगमेंट में संग्रहीत नहीं है। किसी भी मामले में यह ढेर में जीवित वस्तुओं की संख्या से बड़ा नहीं होगा।


जब जीसी कहा जाता है, तो ढेर आमतौर पर भरा होता है। एक और बात यह है कि ऐसा होता है कि स्टैक और हीप एक ही मेमोरी स्पेस के दोनों सिरों से बढ़ते हैं ..
babou

4

कचरा संग्रह के "क्लासिक" विवरणों में (उदाहरण के लिए, मार्क विल्सन, " यूनीप्रोसेसर कूड़ा संग्रह तकनीक ", मेमोरी प्रबंधन पर Int'l कार्यशाला , 1992, ( वैकल्पिक लिंक ), या एंड्रयू एपल के आधुनिक संकलन कार्यान्वयन (कैम्ब्रिज यूनिवर्सिटी प्रेस में वर्णन) 1998)), कलेक्टरों को या तो "मार्क और स्वीप" या "कॉपी करना" के रूप में वर्गीकृत किया जाता है।

मार्क और स्वीप कलेक्टरों ने पॉइंटर-रिवर्सल का उपयोग करके अतिरिक्त स्थान की आवश्यकता से बचा है, जैसा कि @ गाइल्स के उत्तर में वर्णित है। एपेल का कहना है कि नुथ पीटर डिक्शनरी को पॉइंटर-रिवर्सल एल्गोरिदम और हर्बर्ट शोएर और डब्लूएम वेट का श्रेय देता है।

नकल करने वाले कचरा बीनने वालों को अक्सर अतिरिक्त स्थान की आवश्यकता के बिना एक कतार ट्रैवर्सल प्रदर्शन करने के लिए Cheyney के एल्गोरिथ्म का उपयोग किया जाता है। इस एल्गोरिथ्म को CJ Cheyney, "एक नॉनक्रैसिव लिस्ट कॉम्पेक्टिंग एल्गोरिथम", कॉम में पेश किया गया था एसीएम , 13 (11): 677-678, 1970।

कॉपी करने वाले कचरा संग्रहकर्ता में आपके पास मेमोरी का एक हिस्सा होता है जिसे आप इकट्ठा करने की कोशिश कर रहे हैं, जिसे स्पेस कहा जाता है और मेमोरी का एक हिस्सा जिसे आप कॉपी -स्पेस के लिए उपयोग कर रहे हैं । इन-स्पेस को एक कतार के रूप scanमें सबसे पुराने कॉपी-लेकिन-अनसेक्ड रिकॉर्ड की ओर इशारा करते हुए एक पॉइंटर के रूप में आयोजित किया जाता है , और एक freeपॉइंटर इन-स्पेस में अगली मुक्त स्थिति की ओर इशारा करता है। विल्सन के कागज से इस की तस्वीर है:

Cheyney का एल्गोरिथ्म उदाहरण

जैसे ही आप प्रत्येक आइटम को इन-स्पेस में स्कैन करते हैं, तो आप उसके बच्चों को अंतरिक्ष में अंतरिक्ष में freeपॉइंटर से कॉपी करते हैं, और फिर पॉइंटर को बच्चे से अंतरिक्ष में बच्चे की नई प्रति में स्पेस में बदल देते हैं। आपकी डेटा संरचनाएं पेड़ नहीं होने पर (जब एक बच्चा एक से अधिक माता-पिता हो सकते हैं) का उपयोग करने के लिए आपको एक अतिरिक्त चाल की आवश्यकता होती है। उस स्थिति में, जब आप किसी बच्चे को अंतरिक्ष से लेकर अंतरिक्ष में कॉपी करते हैं, तो आपको बच्चे के पुराने संस्करण को बच्चे की नई प्रति को अग्रेषित करने वाले सूचक के साथ लिखना होगा । फिर यदि आप कभी भी किसी अन्य पॉइंटर को उस बच्चे के पुराने संस्करण में स्कैन करते हैं जिसे आप महसूस करते हैं कि यह पहले ही कॉपी हो चुका है, और फिर से कॉपी न करें।


दरअसल, जैसा कि मेरे उत्तर में बताया गया है, मार्क + स्वीप और कॉपी संग्रह दोनों एक ही सार ग्राफ एल्गोरिथ्म हैं। अमूर्त एल्गोरिथम द्वारा उपयोग किए जाने वाले सेटों में एमएस और कॉपी संग्रह केवल उसी तरह से भिन्न होते हैं, और दोनों परिवार शामिल होते हैं, कई वेरिएंट के साथ, सेट कार्यान्वयन तकनीकों के कुछ संयोजन में मैं अपने उत्तर में वर्णन करता हूं। कुछ GC वेरिएंट वास्तव में उसी GC में MS और Copy को मिलाते हैं। एमएस और कॉपी को अलग करने से कुछ को पुस्तकों की संरचना के लिए एक सुविधाजनक तरीके के रूप में देखा जाता है, लेकिन यह एक मनमाना है, और मेरा मानना ​​है कि पुरानी, ​​दृष्टि।
बबौ

@ बाबू: यदि कोई एक कॉपीिंग एल्गोरिथ्म का उपयोग कर रहा है जिसमें आने वाली हर चीज की नकल की जाएगी (धीमी है, लेकिन छोटे प्लेटफार्मों पर उपयोगी हो सकती है जहां काम करने वाला सेट कभी भी इतना बड़ा नहीं होता है), कुछ एल्गोरिदम कुछ सरल हो सकते हैं क्योंकि एक का उपयोग कर सकते हैं पूर्व में एक स्‍क्रैपपैड के रूप में किसी पुनर्निर्मित वस्तु द्वारा अधिग्रहित मेमोरी। एक सीमित क्षमता भी हासिल कर सकता है कि अन्य थ्रेड्स केवल संग्रह के दौरान ऑब्जेक्ट्स पर रीड-ओनली एक्सेस कर सकें, बशर्ते कि प्रत्येक रीड से पहले और बाद में ऑब्जेक्ट की वैधता की जांच करता है, और अगर किसी ऑब्जेक्ट को ले जाया गया है तो फॉरवर्डिंग पॉइंटर का अनुसरण करता है।
सुपरकैट

@ सुपरकैट मुझे यकीन नहीं है कि आप क्या कहना चाह रहे हैं, आपकी मंशा क्या है। आपके कुछ कथन सही प्रतीत होते हैं। लेकिन मुझे समझ में नहीं आता है कि जीसी चक्र समाप्त होने से पहले आप अंतरिक्ष से कैसे उपयोग कर सकते हैं (इसमें अग्रेषण बिंदु शामिल हैं)। और यह किसके लिए एक स्क्रैडपैड होगा? एलगोरिटम को सरल कैसे करें? जीसी के होने के दौरान निष्पादित कई उत्परिवर्ती थ्रेड्स के बारे में, यह काफी हद तक एक ऑर्थोगोनल मुद्दा है, हालांकि यह गंभीर रूप से कार्यान्वयन को प्रभावित कर सकता है। मैं टिप्पणियों में इसे संबोधित करने का प्रयास नहीं करूंगा। इसे केवल पढ़ने के लिए उपयोग में कम समस्याएं उठानी चाहिए, लेकिन शैतान विवरण में है।
Babou
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.