आप वास्तव में सभी जीसी कार्यान्वयन का उपयोग करने के उचित तरीके के बारे में कंबल बयान नहीं कर सकते । वे बेतहाशा भिन्न होते हैं। इसलिए मैं .NET .NET से बात करूंगा जिसे आपने मूल रूप से संदर्भित किया है।
आप किसी भी तर्क या कारण के साथ ऐसा करने के लिए जीसी के व्यवहार को बहुत अच्छी तरह से जानते होंगे।
संग्रह की एकमात्र सलाह जो मैं दे सकता हूं वह है: कभी मत करना।
यदि आप वास्तव में GC के जटिल विवरण जानते हैं, तो आपको मेरी सलाह की आवश्यकता नहीं होगी, इसलिए यह कोई फर्क नहीं पड़ेगा। यदि आप पहले से ही 100% आत्मविश्वास के साथ नहीं जानते हैं तो इससे ऑनलाइन मदद मिलेगी और इस तरह का उत्तर ढूंढना होगा: आपको GC.Clectlect या वैकल्पिक रूप से कॉल नहीं करना चाहिए : आपको यह जानना चाहिए कि GC कैसे काम करता है? अंदर और बाहर, और उसके बाद ही आपको उत्तर पता चलेगा ।
वहाँ एक सुरक्षित जगह यह कुछ अर्थों GC.Collect उपयोग करने के लिए बनाता है :
GC.Collect एक एपीआई उपलब्ध है जिसका उपयोग आप चीजों की रूपरेखा समय के लिए कर सकते हैं। आप एक एल्गोरिथ्म को प्रोफाइल कर सकते हैं, एकत्र कर सकते हैं, और दूसरे एल्गोरिथ्म को तुरंत बाद में जान सकते हैं, यह जानकर कि आपके दूसरे एक के परिणामों को तिरछा करने के दौरान पहले अहंकार की जीसी नहीं हो रही थी।
इस प्रकार की रूपरेखा एकल समय है जो मैं कभी भी किसी को मैन्युअल रूप से एकत्रित करने का सुझाव दूंगा।
वैसे भी वंचित उदाहरण
एक संभव उपयोग मामला है यदि आप वास्तव में बड़ी चीजों को लोड करते हैं, तो वे बड़े ऑब्जेक्ट हीप में समाप्त हो जाएंगे जो सीधे Gen 2 में जाएंगे, हालांकि फिर से Gen 2 लंबे समय तक जीवित वस्तुओं के लिए है क्योंकि यह कम बार इकट्ठा होता है। यदि आप जानते हैं कि आप किसी भी कारण के लिए जनरल 2 में कम जीवित वस्तुओं को लोड कर रहे हैं, तो आप अपने जनरल 2 को छोटा रखने के लिए उन्हें और अधिक तेज़ी से साफ़ कर सकते हैं और यह तेजी से संग्रहित है।
यह सबसे अच्छा उदाहरण है जिसके साथ मैं आ सकता हूं, और यह अच्छा नहीं है - जो LOH दबाव आप यहां बना रहे हैं वह अधिक लगातार संग्रह का कारण बनेगा, और संग्रह इतने लगातार होते हैं - संभावना है कि यह LOH को उसी तरह बाहर निकाल देगा उपवास के रूप में आप इसे अस्थायी वस्तुओं के साथ बाहर उड़ा रहे थे। मैं बस अपने आप को जीसी से बेहतर संग्रह आवृत्ति मानने के लिए खुद पर भरोसा नहीं करता हूं - मैं की तुलना में कहीं अधिक होशियार लोगों द्वारा ट्यून किया गया ।
तो चलिए .NET GC में कुछ शब्दार्थ और तंत्र के बारे में बात करते हैं ... या ..
सब कुछ मुझे लगता है कि मैं .NET जीसी के बारे में जानता हूं
कृपया, जो कोई भी त्रुटि पाता है - मुझे सही करें। अधिकांश जीसी को काला जादू के रूप में जाना जाता है और जब मैंने विवरणों को छोड़ने की कोशिश की, तो मैं अनिश्चित था, मुझे अभी भी कुछ चीजें गलत लगीं।
नीचे जानबूझकर कई विवरण गायब हैं जिनके बारे में मैं निश्चित नहीं हूं, साथ ही साथ जानकारी का एक बड़ा निकाय जिससे मैं अनजान हूं। इस सूचना का उपयोग अपने ख़ुद के जोखिम पर करें।
जीसी अवधारणाओं
.NET GC असंगत समय पर होता है, यही कारण है कि इसे "गैर-नियतात्मक" कहा जाता है, इसका मतलब है कि आप विशिष्ट समय पर होने के लिए इस पर भरोसा नहीं कर सकते। यह एक जेनरेशनल कचरा संग्रहकर्ता भी है, जिसका अर्थ है कि यह आपकी वस्तुओं को कितने जीसी पास से गुजरता है जिसके माध्यम से वे गुजारे हैं।
जनरल 0 ढेर में ऑब्जेक्ट्स 0 संग्रह के माध्यम से रहते हैं, ये हाल ही में बनाए गए हैं इसलिए हाल ही में उनके इंस्टेंटेशन के बाद से कोई संग्रह नहीं हुआ है। आपके जनरल 1 ढेर में ऑब्जेक्ट एक संग्रह पास से गुजरे हैं, और इसी तरह आपके जनरल 2 ढेर में ऑब्जेक्ट 2 संग्रह पास से गुजरे हैं।
अब यह ध्यान देने योग्य है कि यह इन विशिष्ट पीढ़ियों और विभाजनों के अनुसार योग्य है। .NET GC केवल इन तीन पीढ़ियों को पहचानता है, क्योंकि इन तीन ढेरों पर जाने वाले संग्रह पास सभी अलग हैं। कुछ वस्तुएं बच सकती हैं संग्रह हजारों बार गुजरता है। जीसी केवल जनरल 2 हीप विभाजन के दूसरी तरफ इन्हें छोड़ देता है, उन्हें आगे कहीं भी विभाजित करने का कोई मतलब नहीं है क्योंकि वे वास्तव में जनरल 44 हैं; उन पर संग्रह पास जेन 2 ढेर में सब कुछ के समान है।
इन विशिष्ट पीढ़ियों के अर्थिक उद्देश्य हैं, साथ ही कार्यान्वित तंत्र भी हैं जो इनका सम्मान करते हैं, और मैं उन लोगों को एक पल में प्राप्त करूंगा।
एक संग्रह में क्या है
जीसी संग्रह पास की मूल अवधारणा यह है कि यह प्रत्येक ऑब्जेक्ट को एक ढेर स्थान पर जांचता है यह देखने के लिए कि क्या इन वस्तुओं के लिए अभी भी लाइव संदर्भ (जीसी रूट) हैं। यदि किसी ऑब्जेक्ट के लिए GC रूट पाया जाता है, तो इसका मतलब है कि वर्तमान में कोड निष्पादित करना अभी भी संभव है और उस ऑब्जेक्ट का उपयोग कर सकता है, इसलिए इसे हटाया नहीं जा सकता है। हालाँकि यदि किसी ऑब्जेक्ट के लिए GC रूट नहीं मिलता है, तो इसका मतलब है कि रनिंग प्रक्रिया को ऑब्जेक्ट की आवश्यकता नहीं है, इसलिए यह नई ऑब्जेक्ट के लिए मेमोरी को खाली करने के लिए इसे हटा सकता है।
अब वस्तुओं के एक समूह को साफ करने और कुछ को अकेला छोड़ने के बाद, एक दुर्भाग्यपूर्ण दुष्प्रभाव होगा: जीवित वस्तुओं के बीच मुक्त स्थान अंतराल जहां मृत लोगों को हटा दिया गया था। यह स्मृति विखंडन अगर अकेले छोड़ दिया जाता है तो बस स्मृति को बर्बाद कर देगा, इसलिए संग्रह आमतौर पर "संघनन" कहलाता है, जहां वे सभी जीवित वस्तुओं को छोड़ देते हैं और उन्हें एक साथ ढेर में निचोड़ लेते हैं, इसलिए मुक्त स्मृति एक तरफ ढेर के साथ सन्निहित है 0।
अब स्मृति के 3 ढेर के विचार को देखते हुए, सभी संग्रह की संख्या से गुजरते हैं जो वे गुजरे हैं, आइए बात करते हैं कि ये बदलाव क्यों मौजूद हैं।
जनरल ० संग्रह
जनरल 0 सबसे नई वस्तु है, यह बहुत छोटा होता है - इसलिए आप इसे बहुत बार सुरक्षित रूप से एकत्र कर सकते हैं । आवृत्ति यह सुनिश्चित करती है कि ढेर छोटा रहता है और संग्रह बहुत तेजी से होता है क्योंकि वे इतने छोटे ढेर के ऊपर एकत्रित होते हैं। यह एक हेयुरिस्टिक पर कम या ज्यादा आधारित है जो दावा करता है: आपके द्वारा बनाई गई अस्थायी वस्तुओं का एक बड़ा हिस्सा बहुत अस्थायी है, इसलिए अस्थायी वे अब उपयोग के लगभग तुरंत बाद उपयोग नहीं किए जाएंगे या संदर्भित किए जा सकते हैं, और इस तरह एकत्र किया जा सकता है।
जनरल 1 संग्रह
जनरल 1 ऑब्जेक्ट्स, जो वस्तुओं के इस बहुत ही अस्थायी श्रेणी में नहीं आते हैं, अभी भी कम समय तक जीवित रह सकते हैं, क्योंकि अभी भी- निर्मित वस्तुओं का एक बड़ा हिस्सा लंबे समय तक उपयोग नहीं किया जाता है। इसलिए Gen 1 बार-बार इकट्ठा करता है, फिर से इसे छोटा रखता है इसलिए यह संग्रह तेज होता है। हालाँकि यह धारणा कम है कि यह वस्तुएँ Gen 0 से अस्थायी हैं, इसलिए यह Gen 0 की तुलना में कम बार एकत्रित होती हैं
मैं कहूंगा कि मैं स्पष्ट रूप से उन तकनीकी तंत्रों को नहीं जानता हूं जो जनरल 0 के संग्रह पास और जनरल 1 के बीच भिन्न हैं, यदि वे आवृत्ति को इकट्ठा करने के अलावा अन्य सभी पर हैं।
जनरल 2 संग्रह
जनरल 2 अब सभी की माँ को सही होना चाहिए? खैर, हां, यह कमोबेश सही है। यह वह जगह है जहां आपके सभी स्थायी ऑब्जेक्ट रहते हैं - Main()
उदाहरण के लिए आपके जीवन की वस्तु , और सब कुछ जो Main()
संदर्भ देता है क्योंकि वे Main()
आपकी प्रक्रिया के अंत तक आपके रिटर्न तक निहित होंगे ।
यह देखते हुए कि जनरल 2 मूल रूप से सब कुछ के लिए एक बाल्टी है जो अन्य पीढ़ियों को इकट्ठा नहीं कर सकता है, यह ऑब्जेक्ट्स काफी हद तक स्थायी हैं, या लंबे समय तक कम से कम रहते हैं। तो जनरल 2 में जो कुछ भी है उसे बहुत कम पहचानना वास्तव में ऐसा कुछ होगा जिसे एकत्र किया जा सकता है, इसे बार-बार इकट्ठा करने की आवश्यकता नहीं है। यह संग्रह को धीमा करने की अनुमति देता है, क्योंकि यह बहुत कम बार निष्पादित होता है। तो यह मूल रूप से है जहां वे विषम परिदृश्यों के लिए सभी अतिरिक्त व्यवहारों से निपट चुके हैं, क्योंकि उनके पास उन्हें निष्पादित करने का समय है।
बड़ी वस्तु ढेर
जनरल 2 के अतिरिक्त व्यवहार का एक उदाहरण यह है कि यह लार्ज ऑब्जेक्ट हीप पर संग्रह भी करता है। अब तक मैं पूरी तरह से स्मॉल ऑब्जेक्ट हीप के बारे में बात कर रहा हूं, लेकिन .NET रनटाइम ने कुछ आकारों की चीजों को एक अलग हीप के लिए आवंटित किया है क्योंकि मैंने ऊपर संकलन के रूप में संदर्भित किया था। जब छोटे ऑब्जेक्ट हीप पर संग्रह समाप्त होता है, तो कंप्रेशन को ऑब्जेक्ट्स को घूमने की आवश्यकता होती है। अगर Gen 1 में जीवित 10mb ऑब्जेक्ट है, तो संग्रह के बाद संघनन को पूरा करने में अधिक समय लगने वाला है, इस प्रकार Gen 1 का संग्रह धीमा हो जाता है। ताकि 10mb ऑब्जेक्ट बड़े ऑब्जेक्ट हीप को आबंटित किया जाए, और Gen 2 के दौरान एकत्र किया जाए जो इतनी बार चलता है।
अंतिम रूप
एक और उदाहरण फाइनलर्स के साथ ऑब्जेक्ट है। आपने किसी ऑब्जेक्ट पर अंतिम रूप दिया है जो .NETs GC (अप्रबंधित संसाधनों) के दायरे से परे संसाधनों का संदर्भ देता है। अंतिम तरीका एकमात्र तरीका है जो जीसी को एक अप्रबंधित संसाधन की मांग करने के लिए मिलता है - आप अपने प्रक्रिया से लीक नहीं होने को सुनिश्चित करने के लिए मैनुअल संग्रह / हटाने / जारी करने के लिए अपने अंतिम रूप को लागू करते हैं। जब जीसी आपकी वस्तुओं को अंतिम रूप देने में सक्षम हो जाता है, तो आपका कार्यान्वयन अप्रबंधित संसाधन को साफ कर देगा, जिससे जीसी आपकी संसाधन को हटाने के लिए सक्षम हो जाएगी, बिना रिसोर्स लीक के।
जिस तंत्र के साथ फाइनल करते हैं वह अंतिम रूप से सीधे कतार में संदर्भित होने से होता है। जब रनटाइम किसी ऑब्जेक्ट को अंतिम रूप से आवंटित करता है, तो यह उस ऑब्जेक्ट को अंतिम रूप देने के लिए एक संकेतक जोड़ता है, और आपकी ऑब्जेक्ट को जगह में लॉक करता है (जिसे पिनिंग कहा जाता है) इसलिए संघनन इसे स्थानांतरित नहीं करेगा जो अंतिमकरण कतार संदर्भ को तोड़ देगा। जैसे-जैसे संग्रह पास होते जाते हैं, अंततः आपकी वस्तु को जीसी रूट नहीं मिलेगा, लेकिन इसे एकत्र करने से पहले अंतिम रूप दिया जाना चाहिए। इसलिए जब ऑब्जेक्ट मृत हो जाता है, तो संग्रह इसे अंतिम पंक्ति से संदर्भ स्थानांतरित कर देगा और उस पर एक संदर्भ रख देगा जिसे "FReachable" कतार के रूप में जाना जाता है। फिर संग्रह जारी है। भविष्य में एक और "गैर-नियतात्मक" समय पर, फाइनल थ्रेड के रूप में जाना जाने वाला एक अलग धागा FReachable क्यू के माध्यम से जाएगा, संदर्भित ऑब्जेक्ट्स में से प्रत्येक के लिए फाइनलर्स को निष्पादित करेगा। यह समाप्त होने के बाद, FReachable कतार खाली है, और यह प्रत्येक ऑब्जेक्ट के हेडर पर थोड़ा सा फ़्लिप किया है जो कहता है कि उन्हें अंतिम रूप देने की आवश्यकता नहीं है (इस बिट को मैन्युअल रूप से भी फ़्लिप किया जा सकता हैGC.SuppressFinalize
जो Dispose()
तरीकों में आम है ), मुझे यह भी संदेह है कि इसने वस्तुओं को अनपिन कर दिया है, लेकिन मुझे उस पर उद्धृत नहीं करते हैं। अगला संग्रह जो इस वस्तु के ढेर पर आता है, वह अंत में इसे एकत्र करेगा। जनरल 0 संग्रह भी उस अंतिमकरण की आवश्यकता वाली वस्तुओं पर ध्यान नहीं देते हैं, यह स्वचालित रूप से उन्हें बढ़ावा देता है, यहां तक कि उनकी जड़ की जांच किए बिना। एक अनियंत्रित वस्तु को Gen 1 में अंतिम रूप देने की आवश्यकता है, FReachable
कतार में उछाला जाएगा , लेकिन संग्रह इसके साथ कुछ और नहीं करता है, इसलिए यह Gen 2 में रहता है। इस तरह से, सभी ऑब्जेक्ट्स जिनमें एक फाइनल होता है, और नहीं GC.SuppressFinalize
जनरल 2 में एकत्र किया जाएगा।