एक कूड़ा उठाने वाला पूरी मेमोरी को हर कलेक्शन पर स्कैन करने से कैसे रोकता है?


16

कुछ (कम से कम मोनो और .NET के) कचरा संग्रहकर्ताओं के पास एक अल्पकालिक मेमोरी क्षेत्र होता है जिसे वे अक्सर स्कैन करते हैं, और एक माध्यमिक मेमोरी क्षेत्र जिसे वे कम बार स्कैन करते हैं। मोनो इसे नर्सरी कहते हैं।

यह पता लगाने के लिए कि किन वस्तुओं को निपटाया जा सकता है, वे सभी वस्तुओं को जड़ों, स्टैक और रजिस्टरों से स्कैन करते हैं और उन सभी वस्तुओं का निपटान करते हैं जिन्हें अब संदर्भित नहीं किया जा रहा है।

मेरा सवाल यह है कि वे सभी मेमोरी को हर कलेक्ट पर स्कैन करने से कैसे रोकें? सिद्धांत रूप में, यह पता लगाने का एकमात्र तरीका है कि क्या वस्तुएं अब उपयोग में नहीं हैं, सभी वस्तुओं और उनके सभी संदर्भों को स्कैन करना है। हालाँकि, यह OS को मेमोरी को स्वैप करने से रोकता है, भले ही यह एप्लिकेशन द्वारा उपयोग में न हो और काम की एक बड़ी मात्रा की तरह महसूस करता है, जिसे "नर्सरी कलेक्शन" के लिए भी आवश्यक है। यह महसूस नहीं होता है कि वे नर्सरी का उपयोग करके बहुत अधिक जीत रहे हैं।

क्या मुझे कुछ याद आ रहा है या कचरा संग्रहकर्ता वास्तव में हर वस्तु और हर सन्दर्भ को स्कैन कर रहा है जब भी यह एक संग्रह करता है?


1
एक अच्छा अवलोकन एंजेलिका लैंगर द्वारा लिखित एक लेख द आर्ट ऑफ गारबेज कलेक्शन ट्यूनिंग में है। औपचारिक रूप से, यह जावा में कैसे किया जाता है इसके तरीके के बारे में है, लेकिन प्रस्तुत अवधारणाएं बहुत अधिक भाषा अज्ञेय हैं
gnat

जवाबों:


14

मौलिक अवलोकन जो पीढ़ीगत कचरा-संग्रह को सभी पुरानी पीढ़ी की वस्तुओं को स्कैन करने से बचने की अनुमति देते हैं:

  1. एक संग्रह के बाद, सभी ऑब्जेक्ट जो अभी भी मौजूद हैं, कुछ न्यूनतम पीढ़ी के होंगे (जैसे कि .net में, Gen0 संग्रह के बाद, सभी ऑब्जेक्ट Gen1 या Gen2 हैं; Gen1 या Gen2 संग्रह के बाद, सभी ऑब्जेक्ट Gen2 हैं)।
  2. एक वस्तु, या उसका भाग, जिसे एक संग्रह के बाद से नहीं लिखा गया है जो कि पीढ़ी एन या उच्चतर को सब कुछ बढ़ावा देता है, जिसमें निम्न पीढ़ियों की वस्तुओं का कोई संदर्भ नहीं हो सकता है।
  3. यदि कोई वस्तु एक निश्चित पीढ़ी तक पहुँच गई है, तो उसे निचली पीढ़ियों को एकत्रित करते समय अपनी अवधारण सुनिश्चित करने के लिए उपलब्ध होने की आवश्यकता नहीं है।

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

ध्यान दें, btw, कि भले ही कोई यह पता नहीं लगा सके कि वस्तुओं को संशोधित किया गया है और प्रत्येक जीसी पास पर सब कुछ स्कैन करना होगा, जेनेरिक कचरा संग्रह अभी भी एक कॉम्पैक्ट कलेक्टर के "स्वीप" चरण के प्रदर्शन में सुधार कर सकता है। कुछ एम्बेडेड वातावरणों में (विशेषकर उन लोगों में जहां अनुक्रमिक और यादृच्छिक मेमोरी एक्सेस के बीच गति में बहुत कम या कोई अंतर नहीं है), टैगिंग संदर्भों की तुलना में स्मृति के चारों ओर घूमना अपेक्षाकृत महंगा है। नतीजतन, भले ही "निशान" चरण को जेनरेशनल कलेक्टर का उपयोग करके ऊपर नहीं उठाया जा सकता है, "स्वीप" चरण को तेज करना सार्थक हो सकता है।


मेमोरी ब्लॉक को किसी भी सिस्टम में ले जाना महंगा है, इसलिए स्वीप को बेहतर बनाना आपके क्वाड Ghz CPU सिस्टम पर भी लाभ है।
gbjbaanb 10

@ जीबीजैनब: कई मामलों में, जीवित वस्तुओं को खोजने के लिए सब कुछ स्कैन करने की लागत महत्वपूर्ण और आपत्तिजनक होगी, भले ही ऑब्जेक्ट्स को स्थानांतरित करना पूरी तरह से स्वतंत्र था। नतीजतन, किसी को पुरानी वस्तुओं को स्कैन करने से बचना चाहिए। दूसरी ओर, पुरानी वस्तुओं को संकुचित करने से बचना एक सरल अनुकूलन है जिसे सरल रूपरेखा पर भी पूरा किया जा सकता है। BTW, यदि कोई एक छोटे एम्बेडेड सिस्टम के लिए GC फ्रेमवर्क डिजाइन कर रहा था, तो अपरिवर्तनीय वस्तुओं के लिए घोषणात्मक समर्थन सहायक हो सकता है। ट्रैक करना कि क्या एक परिवर्तनशील वस्तु बदल गई है, कठिन है, लेकिन एक अच्छी तरह से कर सकता है ...
सुपरकैट

... बस यह मान लें कि परिवर्तनशील वस्तुओं को हर जीसी पास को स्कैन करने की आवश्यकता होती है लेकिन अपरिवर्तनीय वस्तुएं नहीं होती हैं। यहां तक ​​कि अगर किसी अपरिवर्तनीय वस्तु के निर्माण का एकमात्र तरीका परस्पर स्थान में "प्रोटोटाइप" का निर्माण करना था और फिर उसे कॉपी करना था, तो एकल अतिरिक्त कॉपी ऑपरेशन ऑब्जेक्ट को भविष्य के जीसी संचालन में स्कैन करने की आवश्यकता से बच सकता है।
सुपरकैट

संयोग से, 6502 माइक्रोप्रोसेसरों (और शायद अन्य) के लिए BASIC के Microsoft द्वारा व्युत्पन्न कार्यान्वयन पर कचरा-संग्रह प्रदर्शन कुछ मामलों में बहुत बढ़ाया जा सकता है, अगर एक प्रोग्राम जिसने बहुत सारे तार उत्पन्न किए जो कभी नहीं बदलेगा, ने "अगला" कॉपी किया। स्ट्रिंग आवंटन "सूचक" स्ट्रिंग स्पेस के शीर्ष "सूचक के लिए। इस तरह के बदलाव से कचरा इकट्ठा करने वाले को किसी भी पुराने तार की जांच करने से रोका जा सकेगा कि क्या उन्हें अभी भी जरूरत है। कमोडोर 64 शायद ही हाई-टेक था, लेकिन इस तरह के "जेनेशनल" जीसी वहां भी मदद करेंगे।
सुपरकैट

7

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

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


3

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


1

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

मुख्य बिंदु यह है कि कचरा संग्रहकर्ता संकलक के साथ मिलकर और बाकी के समय के साथ भ्रम को बनाए रखने के लिए काम करता है कि यह स्मृति को देख रहा है।


मुझे यकीन नहीं है कि 1970 के उत्तरार्ध से पहले minicomputers और mainframes में कचरा संग्रह के दृष्टिकोण का क्या उपयोग किया गया था, लेकिन Microsoft BASIC कचरा संग्रहकर्ता, कम से कम 6502 मशीनों पर, स्मृति के शीर्ष पर अपना "अगला स्ट्रिंग" सूचक सेट करेगा, और खोज करेगा सभी स्ट्रिंग संदर्भ "अगला स्ट्रिंग पॉइंटर" के नीचे उच्चतम पता खोजने के लिए। उस स्ट्रिंग को "अगले स्ट्रिंग पॉइंटर" के ठीक नीचे कॉपी किया जाएगा, और उस पॉइंटर को इसके ठीक नीचे पार्क किया जाएगा। एल्गोरिथ्म फिर दोहराना होगा। कोड के लिए पॉइंटर्स को प्रदान करना संभव था ...
सुपरकैट

... जेनेरिक कलेक्शन जैसा कुछ। मैंने कभी-कभी सोचा है कि प्रत्येक पीढ़ी के शीर्ष के पते को ध्यान में रखते हुए और प्रत्येक जीसी चक्र से पहले और बाद में कुछ पॉइंटर-स्वैप ऑपरेशन को जोड़कर "जेनेेशनल" संग्रह को लागू करने के लिए BASIC को पैच करना कितना कठिन होगा। जीसी प्रदर्शन अभी भी बहुत बुरा होगा, लेकिन कई मामलों में दसियों सेकंड से दसवें सेकंड तक मुंडा हो सकता है।
सुपरकैट

-2

असल में ... जीसी "बकेट" का उपयोग अलग करने के लिए करता है जो उपयोग में है और जो नहीं है। एक बार जब यह जांच कर लेता है, तो यह उन चीजों को मिटा देता है जो उपयोग में नहीं होती हैं और बाकी सब को दूसरी पीढ़ी में ले जाती हैं (जो कि 1 पीढ़ी से कम बार जांच की जाती है) और फिर उन चीजों को स्थानांतरित करती है जो अभी भी 2 जी 3 जी के लिए उपयोग में नहीं हैं।

इसलिए, तीसरी पीढ़ी की चीजें आमतौर पर ऐसी वस्तुएं हैं जो किसी कारण से खुली हुई हैं, और जीसी वहां बहुत बार जांच नहीं करता है।


1
लेकिन यह कैसे पता चलता है कि कौन सी वस्तुएं उपयोग में हैं?
पीटर वैन जिन्केल

यह ट्रैक करता है कि कौन सी वस्तुएं पुन: प्राप्य कोड से पहुंच योग्य हो सकती हैं। एक बार जब कोई ऑब्जेक्ट किसी भी कोड से पहुंच योग्य नहीं होता है जो निष्पादित कर सकता है (कहें, एक विधि के लिए कोड जो वापस आ गया है) तो जीसी जानता है कि इसे इकट्ठा करना सुरक्षित है
JohnL

आप दोनों लोग बता रहे हैं कि जीसी कैसे सही होते हैं, न कि वे कैसे कुशल होते हैं। प्रश्न से देखते हुए, ओपी जानता है कि पूरी तरह से अच्छी तरह से।

@delnan हाँ मैं इस सवाल का जवाब दे रहा था कि यह कैसे जानता है कि कौन सी वस्तुएं उपयोग में हैं, जो कि पीटर की टिप्पणी में थी।
जॉनएल

-5

इस GC द्वारा आमतौर पर उपयोग किया जाने वाला एल्गोरिथ्म Na usuallyve मार्क-एंड-स्वीप है

आपको इस तथ्य के बारे में भी पता होना चाहिए कि यह सी # द्वारा प्रबंधित नहीं है, लेकिन तथाकथित सीएलआर द्वारा


यही भावना मुझे मोनो के कचरा संग्रहकर्ता के बारे में पढ़ने से मिली। हालाँकि, जो मुझे समझ में नहीं आ रहा है वह यह है कि अगर वे कभी भी एकत्रित होने वाले पूर्ण कार्य सेट को स्कैन कर रहे हैं, तो उनके पास एक जेनरेशनल कलेक्टर होता है जिसके साथ GEN-0 का संग्रह बहुत तेजी से होता है। यह कभी भी 2GB के वर्किंग सेट के साथ तेज़ कैसे हो सकता है?
पीटर वैन जिन्कल

खैर, मोनो के लिए वास्तविक GC Sgen है, आपको इस मोनो-project.com/Generational_GC या कुछ ऑनलाइन लेख schani.wordpress.com/tag/mono infoq.com/news/2011/01/SGen को पढ़ना चाहिए , बिंदु यह है कि सीएलआर और सीएलआई जैसी नई तकनीकों में वास्तव में मॉड्यूलर डिजाइन है, भाषा सीएलआर के लिए कुछ व्यक्त करने का एक तरीका है और न ही द्विआधारी कोड का उत्पादन करने का तरीका है। आपका प्रश्न कार्यान्वयन विवरणों के बारे में है और एल्गोरिदम के बारे में नहीं है, क्योंकि एक एल्गोरिथ्म में अभी भी कार्यान्वयन नहीं है, आपको सिर्फ मोनो से तकनीकी पेपर और लेख पढ़ना चाहिए, कोई और नहीं।
15:8 बजे user827992

मैं उलझन में हूं। कचरा संग्रहकर्ता द्वारा उपयोग की जाने वाली रणनीति एक एल्गोरिथ्म नहीं है?
पीटर वैन जिंकेल

2
-1 ओपी को भ्रमित करना बंद करें। जीसी सीएलआर का हिस्सा है और भाषा-विशिष्ट बिल्कुल भी प्रासंगिक नहीं है। एक जीसी ज्यादातर जिस तरह से यह ढेर बाहर देता है और गम्यता निर्धारित करता है की विशेषता है, और बाद है सब एल्गोरिथ्म (रों) कि के लिए इस्तेमाल के बारे में। जबकि एल्गोरिथ्म के कई कार्यान्वयन हो सकते हैं, और आपको कार्यान्वयन विवरण में नहीं फंसना चाहिए, एल्गोरिथ्म अकेले निर्धारित करता है कि कितनी वस्तुओं को स्कैन किया गया है। एक पीढ़ीगत जीसी बस एक एल्गोरिथ्म + ढेर लेआउट है जो "जेनरेशनल परिकल्पना" का उपयोग करने का प्रयास करता है (जो कि अधिकांश ऑब्जेक्ट युवा मर जाते हैं)। ये भोले नहीं हैं।

4
एल्गोरिथ्म! = कार्यान्वयन वास्तव में, लेकिन एक कार्यान्वयन केवल इस दूर तक विचलन कर सकता है इससे पहले कि यह एक अलग एल्गोरिथ्म का कार्यान्वयन बन जाए। जीसी दुनिया में एक एल्गोरिथ्म विवरण, बहुत विशिष्ट है और इसमें नर्सरी संग्रह पर पूरे ढेर को स्कैन नहीं करने और अंतर जनरेशनल पॉइंटर्स कैसे पाए जाते हैं और संग्रहीत किए जाते हैं जैसी चीजें शामिल हैं। यह सच है कि एक एल्गोरिथ्म आपको यह नहीं बताता है कि एल्गोरिथ्म का एक विशिष्ट चरण कितना समय लगेगा, लेकिन यह इस प्रश्न के लिए बिल्कुल भी प्रासंगिक नहीं है।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.