GC.Collect () का उपयोग करने के बारे में क्या गलत है?


103

हालाँकि मैं इस फ़ंक्शन के साथ खेलने के गंभीर निहितार्थों को समझता हूं (या कम से कम जो मैं सोचता हूं), मैं यह देखने में विफल हूं कि यह इन चीजों में से एक क्यों बन रहा है, जो सम्मानजनक प्रोग्रामर कभी भी उपयोग नहीं करेंगे, यहां तक ​​कि उन लोगों को भी जो नहीं जानते हैं यह किस लिए है।

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

प्रश्न: इस मामले में, दूसरे चरण में प्रवेश करने से पहले GC.Collect () को कॉल करना बुद्धिमानी नहीं होगी?

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

ध्यान दें: जैसा कि आप में से कुछ ने बताया है, .NET इस तरह से एक आवेदन के लिए सबसे अच्छा मंच नहीं हो सकता है, लेकिन यह इस प्रश्न के दायरे से बाहर है। इरादा स्पष्ट करना है कि क्या GC.Collect () कॉल किसी एप्लिकेशन के समग्र व्यवहार / प्रदर्शन को बेहतर कर सकता है या नहीं। हम सभी इस बात से सहमत हैं कि जिन परिस्थितियों में आप ऐसा करेंगे, वे बेहद दुर्लभ हैं, लेकिन फिर, जीसी अनुमान लगाने की कोशिश करता है और यह ज्यादातर समय पूरी तरह से करता है, लेकिन यह अभी भी अनुमान लगाने के बारे में है।

धन्यवाद।


24
"कार्यक्रम के प्रवाह में थोड़ी सी भी तबाही भयावह परिणाम ला सकती है ... किसी की मृत्यु हो सकती है" - क्या आप सुनिश्चित हैं कि C # .NET आपके उद्देश्यों के लिए पर्याप्त रूप से निर्धारक है?
स्टीव जेसप

4
विंडोज और न ही .NET वास्तविक समय प्लेटफ़ॉर्म हैं और इसलिए आप प्रदर्शन मेट्रिक्स की गारंटी नहीं दे सकते, कम से कम मानव जीवन को खतरे में डालने के लिए पर्याप्त नहीं हैं। मैं वनबोन से सहमत हूं कि या तो आप अतिरंजित हैं या लापरवाह हैं।
सर्जियो अकोस्टा

3
LOL "इन चीजों में से एक जो सम्मानजनक प्रोग्रामर कभी भी उपयोग नहीं करेंगे, यहां तक ​​कि उन लोगों को भी जो यह नहीं जानते कि यह क्या है"! प्रोग्रामर जो सामान का उपयोग करते हैं, वे यह नहीं जानते कि मेरी पुस्तक में शायद ही सबसे अधिक सम्मानजनक है। :)
दैग

जवाबों:


87

रिको के ब्लॉग से ...

नियम 1

मत करो।

यह वास्तव में सबसे महत्वपूर्ण नियम है। यह कहना उचित है कि GC.Collect () के अधिकांश उपयोग एक बुरे विचार हैं और मैं उस में कुछ विस्तार से मूल पोस्टिंग में गया था, इसलिए मैं यहां सभी को नहीं दोहराऊंगा। तो चलिए आगे बढ़ते हैं ...

नियम # २

GC.Collect () को कॉल करने पर विचार करें यदि कुछ गैर-आवर्ती घटना बस हो गई है और इस घटना से बहुत पुरानी वस्तुओं के मरने की संभावना है।

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

तो ऐसा लगता है कि यह स्थिति नियम # 2 के तहत गिर सकती है, आप जानते हैं कि समय का एक क्षण है जहां बहुत सारी पुरानी वस्तुओं की मृत्यु हो गई है, और यह गैर-आवर्ती है। हालांकि, रीको के बिदाई शब्दों को मत भूलना।

नियम # 1 को मजबूत सबूत के बिना नियम # 2 को ट्रम्प करना चाहिए।

नापना, नापना, नापना।


9
मैं कहूंगा कि यह सिर्फ पुरानी बात है। कुछ भी वास्तव में बुरा या खतरनाक नहीं है यदि आप जानते हैं कि आप क्या कर रहे हैं और इसलिए जानते हैं कि कब और कैसे करना है, साथ ही साथ इसके दुष्प्रभाव भी हैं। दुनिया को बचाने के लिए घटिया प्रोग्रामर से xxxx का इस्तेमाल न करने जैसी बातें कहीं जाती हैं: D
जॉर्ज कॉर्डोबा

यह भी देखें stackoverflow.com/questions/233596/…
Ian Ringrose

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

58

यदि आप उत्पादन कोड में GC.Collect () कहते हैं, तो आप अनिवार्य रूप से घोषित कर रहे हैं कि आप अधिक जानते हैं तो GC के लेखक। ऐसा हो सकता है। हालांकि यह आमतौर पर नहीं है, और इसलिए दृढ़ता से हतोत्साहित किया जाता है।


3
यह बहुत सच है, लेकिन मुझे नहीं पता कि क्या वे ऐसी धारणाएं बना सकते हैं जो सभी घटनाओं के लिए लागू होती हैं।
मास्टर्मास्टिक

2
@ नहीं, वे नहीं कर सकते। लेकिन क्या आप ऐसा करने के लिए बेहतर स्थिति में हैं? या क्या आप विशिष्ट हार्डवेयर, एक विशिष्ट ओएस संस्करण और इसी तरह से कोड लिखने जा रहे हैं? इस पर दर्द / लाभ अनुपात बहुत अधिक है।
दाग़

2
@ TheDag IMO बेशक मैं हूं। जब मैं मेमोरी रिलीज़ कर रहा होता हूं और व्हाट्सएप नहीं करता हूं तो मुझे वास्तव में हार्डवेयर की परवाह नहीं है क्योंकि इससे निपटने के लिए ओएस काम है। मैं ओएस के बारे में परवाह नहीं करता हूं क्योंकि मेरे पास उन सभी के लिए एक इंटरफ़ेस है जो मैं प्रोग्रामिंग कर रहा हूं। (उदाहरण के लिए मुझे परवाह नहीं है कि यह विंडोज, मैक, या लिनक्स है: जब मैं C / C ++ में मेमोरी फ्रीज कर रहा / रही हूं तो यह नया / डिलीट मैलोका / डीलॉक है)। मैं हमेशा गलत हो सकता हूं इसलिए मुझे सही करने के लिए स्वतंत्र महसूस करें।
MasterMastic

@MasterMastic में mallocकेवल एक बहुत ही सरल इंटरफ़ेस है, और यह कार्यान्वयन के लिए पर्याप्त भिन्न हो सकते हैं। यह सब इस बात पर निर्भर करता है कि आप किस तरह की समस्या को हल करने की कोशिश कर रहे हैं। यदि malloc"बहुत अच्छा" था, तो आपको बफर पूलिंग की आवश्यकता नहीं होगी, क्या आप करेंगे? C / C ++ विकास उन उदाहरणों से भरा है , जहां आप OS / रनटाइम / लाइब्रेरीज़ का अनुमान लगाने की कोशिश करते हैं क्योंकि आप बेहतर जानते हैं (और कभी-कभी, आप वास्तव में करते हैं)। कई प्रदर्शन-महत्वपूर्ण अनुप्रयोग पूरी तरह से सिस्टम / रनटाइम आवंटनकर्ताओं का उपयोग करने से बचते हैं। स्टार्टअप में सभी मेमोरी को प्री-आवंटित करने के लिए उपयोग किए जाने वाले गेम (निरंतर आकार के सरणियाँ आदि)।
लुआण

24

तो जब आप .NET वर्ड या एमएस एक्सेल जैसे COM ऑब्जेक्ट का उपयोग कर रहे हैं, तो कैसे करें। GC.CollectCOM ऑब्जेक्ट जारी करने के बाद कॉल किए बिना हमने पाया है कि वर्ड या एक्सेल एप्लिकेशन इंस्टेंस अभी भी मौजूद हैं।

वास्तव में हमारे द्वारा उपयोग किया जाने वाला कोड है:

Utils.ReleaseCOMObject(objExcel)

' Call the Garbage Collector twice. The GC needs to be called twice in order to get the
' Finalizers called - the first time in, it simply makes a list of what is to be finalized,
' the second time in, it actually does the finalizing. Only then will the object do its 
' automatic ReleaseComObject. Note: Calling the GC is a time-consuming process, 
' but one that may be necessary when automating Excel because it is the only way to 
' release all the Excel COM objects referenced indirectly.
' Ref: http://www.informit.com/articles/article.aspx?p=1346865&seqNum=5
' Ref: http://support.microsoft.com/default.aspx?scid=KB;EN-US;q317109
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

तो क्या यह कचरा संग्रहकर्ता का गलत उपयोग होगा? यदि ऐसा है तो हम मरने के लिए इंटरोप ऑब्जेक्ट कैसे प्राप्त करते हैं? इसके अलावा, अगर इसे इस तरह इस्तेमाल किया जा करने के लिए होती है, क्यों है GCकी Collectविधि भी Public?


3
यह एक महान नया StackOverflow प्रश्न होगा, अर्थात: GC को कॉल किए बिना COM इंस्टेंस को कैसे मिटाएँ। विशेष रूप से अप्रबंधित परिपत्र संदर्भों के संबंध में। यह उन चुनौतियों में से एक है जिसने मुझे मेरे VB6 आउटलुक ऐड-इन को C # में अपग्रेड करने से सावधान किया। (हमने वीबी के पक्ष में कोडिंग पैटर्न और परीक्षण मामलों को विकसित करने के लिए बहुत काम किया था जो गारंटी देता है कि COM संदर्भ एक नियतकालिक फैशन में मारे गए थे जब कोई ज़रूरत नहीं थी)।
rkagerer

2
यदि यह सामान्य रूप से COM ऑब्जेक्ट पर लागू होता है, तो शायद यह एक वैध परिदृश्य है। लेकिन बल्ले से मैं कहूंगा कि समस्या यह है कि आप एक COM डेस्कटॉप के रूप में एक इंटरैक्टिव डेस्कटॉप के लिए डिज़ाइन किए गए क्लाइंट एप्लिकेशन का उपयोग कर रहे हैं। MSDN नॉलेज बेस से: "Microsoft वर्तमान में अनुशंसा नहीं करता है, और समर्थन नहीं करता है, किसी भी अप्राप्य, गैर-संवादात्मक क्लाइंट एप्लिकेशन या घटक (ASP, ASP.NET, DCOM और NT सेवाओं सहित) से Microsoft Office अनुप्रयोगों का स्वचालन, क्योंकि Office जब कार्यालय इस वातावरण में चलाया जाता है तो अस्थिर व्यवहार और / या गतिरोध प्रदर्शित कर सकता है।
17

2
@ TheDag - Microsoft अनुशंसा नहीं कर सकता है, लेकिन हम में से कई को पुराने वीबी 6 कोड को पोर्ट इंटरॉप के साथ .नेट विंडोज एप्स के साथ पोर्ट करना पड़ा है। मैंने तब तक काम के महीनों का समय बिताया जब तक कि मुझे एक बड़े VB6 से .Net रूपांतरण परियोजना के लिए सभी अदृश्य फांसी के संदर्भों से छुटकारा नहीं मिल गया। हालांकि रिवर्स असाइनमेंट ऑर्डर में जारी करना सीखना और संग्रह सहित स्थानीय सभी कॉम को स्थानीय रेफरी को रखना, हालांकि इसमें मदद मिली।
डिब

15

खैर, जीसी उन चीजों में से एक है जिनसे मेरा प्रेम / नफरत का रिश्ता है। हमने इसे विस्टाडीबी के माध्यम से अतीत में तोड़ दिया है और इसके बारे में ब्लॉग किया है। उन्होंने इसे ठीक कर दिया है, लेकिन इस तरह की चीजों पर उनसे सुधार प्राप्त करने के लिए एक लंबा समय लगता है।

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

सामान्य तौर पर आपको Collectतब तक नहीं जोड़ना चाहिए जब तक आप एक तथ्य के लिए नहीं जानते हैं कि आपने सिर्फ एक टन मेमोरी को डंप किया है और यह मध्य जीवन संकट में चला जाएगा यदि जीसी अब इसे साफ नहीं करता है।

आप खराब GC.Collectबयानों की एक श्रृंखला के साथ पूरी मशीन को खराब कर सकते हैं। एक एकत्रित कथन की आवश्यकता लगभग हमेशा एक बड़ी अंतर्निहित त्रुटि की ओर इशारा करती है। स्मृति रिसाव को आमतौर पर संदर्भों और यह समझने की कमी के साथ करना पड़ता है कि वे कैसे काम करते हैं। या उन IDisposableवस्तुओं का उपयोग करना जिनकी आवश्यकता नहीं है और GC पर बहुत अधिक भार डाल रहे हैं।

सिस्टम प्रदर्शन काउंटरों के माध्यम से जीसी में बिताए समय के% को बारीकी से देखें। यदि आप अपने ऐप को जीसी में 20% या उससे अधिक समय का उपयोग करते हुए देखते हैं, तो आपके पास गंभीर वस्तु प्रबंधन मुद्दे (या असामान्य उपयोग पैटर्न) हैं। आप हमेशा उस समय को कम से कम करना चाहते हैं जब जीसी खर्च करता है क्योंकि यह आपके पूरे ऐप को गति देगा।

यह भी ध्यान रखना महत्वपूर्ण है कि जीसी कार्यस्थलों की तुलना में सर्वरों पर अलग है। मैंने उन दोनों के परीक्षण नहीं करने वाले लोगों के साथ समस्याओं को ट्रैक करने के लिए कई छोटी-छोटी मुश्किलें देखी हैं (या यह भी नहीं जानते कि उनके दो हैं)।

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


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

5
कोई पूरी मशीन को कैसे खराब कर सकता है?
एडम आर। ग्रे

13

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


12

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


10

GC.Collect () को कॉल करने के सबसे बड़े कारणों में से एक है जब आपने अभी-अभी एक महत्वपूर्ण कार्यक्रम किया है जो बहुत सारे कचरे का निर्माण करता है, जैसे कि आप क्या वर्णन करते हैं। GC.Collect () को कॉल करना यहां एक अच्छा विचार हो सकता है; अन्यथा, जीसी यह नहीं समझ सकता है कि यह एक 'एक बार' घटना थी।

बेशक, आपको इसे प्रोफाइल करना चाहिए, और अपने लिए देखना चाहिए।


9

ठीक है, जाहिर है कि आपको गैर-वास्तविक समय कचरा संग्रह वाली भाषाओं में वास्तविक समय की आवश्यकताओं के साथ कोड नहीं लिखना चाहिए।

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


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

7

GC.Collect () कॉलिंग सीएलआर को यह देखने के लिए स्टैक वॉक करने के लिए मजबूर करती है कि क्या प्रत्येक वस्तु को संदर्भों की जांच के बिना जारी किया जा सकता है। यदि वस्तुओं की संख्या अधिक है, तो यह स्केलेबिलिटी को प्रभावित करेगा, और अक्सर कचरा संग्रह को ट्रिगर करने के लिए भी जाना जाता है। सीएलआर पर भरोसा करें और उचित होने पर कचरा इकट्ठा करने वाले को स्वयं चलने दें।


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

3
मैं धीमी प्रदर्शन की तुलना में आउट ऑफ मेमोरी अपवाद के कारण ऐप क्रैश के बारे में अधिक चिंतित हूं क्योंकि ऐप / जीसी उन चीजों को बाहर फेंक रहा था जिनकी अब आवश्यकता नहीं है। क्या किसी को पता है कि क्यों Microsoft OOM अपवाद को बिना FIRST कचरा फेंकने के लिए प्रकट करता है? (यह स्पष्ट कदम के बिना - या क्यों इस कदम प्रकट नहीं होता है की कम से कम एक व्याख्या यह OOM अपवाद मुझे यकीन है कि मैं हो रहा "स्वचालित रूप से" बातों में कोई विश्वास है नहीं कर रहा हूँ फेंकने से पहले का प्रयास किया जा करने के लिए "जिस तरह से वे करना होता है।"
वंडरबर्ड

6

वास्तव में, मुझे नहीं लगता कि GC.Collect को कॉल करना बहुत बुरा व्यवहार है।
ऐसे मामले हो सकते हैं जब हमें इसकी आवश्यकता होती है। उदाहरण के लिए, मेरे पास एक फॉर्म है, जो एक थ्रेड चलाता है, जो एक डेटाबेस में डिफरेंट टेबल खोलता है, एक BLOB फील्ड में टेम्पररी फाइल में कंटेंट को एक्सट्रैक्ट करता है, फाइल को एन्क्रिप्ट करता है, फिर फाइल को एक बाइनरीस्ट्रीम में पढ़ता है और एक BLOB में वापस आ जाता है। किसी अन्य तालिका में फ़ील्ड।

पूरे ऑपरेशन में काफी मेमोरी लगती है, और यह तालिकाओं में पंक्तियों की संख्या और फ़ाइल सामग्री के आकार के बारे में निश्चित नहीं है।

मुझे अक्सर OutofMemory Exception मिलती थी और मुझे लगता था कि यह समय-समय पर GC.Collect को काउंटर वेरिएबल पर चलाने में समझदारी होगी। मैं एक काउंटर बढ़ाता हूं और जब एक निर्दिष्ट स्तर तक पहुंच जाता है, तो जीसी को किसी भी कचरे को इकट्ठा करने के लिए बुलाया जाता है, जो कि हो सकता है और अप्रत्याशित स्मृति लीक के कारण खोए किसी भी मेमोरी को पुनः प्राप्त करने के लिए।

इसके बाद, मुझे लगता है कि यह अच्छी तरह से काम कर रहा है, कम से कम कोई अपवाद नहीं !!!
मैं निम्नलिखित तरीके से कॉल करता हूं:

var obj = /* object utilizing the memory, in my case Form itself */
GC.Collect(GC.GetGeneration(obj ,GCCollectionMode.Optimized).

5

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

नतीजतन, कॉलिंग GC.Collectसिस्टम द्वारा किए जाने वाले काम की कुल मात्रा को बढ़ाने के लिए उपयुक्त है। यह अगले संग्रह की घटना में देरी करेगा, लेकिन संभवतः तुरंत उतना ही काम करेगा जितना कि अगले संग्रह को होने पर आवश्यक होगा; इस बिंदु पर कि अगला संग्रह कब हुआ होगा, संग्रह करने में लगने वाला कुल समय लगभग उसी तरह का GC.Collectरहा होगा जिसे नहीं बुलाया गया था , लेकिन सिस्टम में कुछ कचरा जमा हो जाएगा, जिसके कारण सफल संग्रह की आवश्यकता जितनी जल्दी GC.Collectनहीं थी कहा जाता है।

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


5

एक लूप में छवियां बनाना - भले ही आप निपटान कहते हैं, स्मृति पुनर्प्राप्त नहीं होती है। हर बार कचरा इकट्ठा होता है। मैं अपने फोटो प्रोसेसिंग ऐप पर 1.7 जीबी मेमोरी से 24 एमबी तक चला गया और प्रदर्शन उत्कृष्ट है।

पूरी तरह से समय है कि आपको GC.Collect को कॉल करने की आवश्यकता है।


2
कॉलिंग Disposeहै नहीं होना चाहिए कामयाब स्मृति को छोड़ दें। आपको पता नहीं लगता है कि .NET में मेमोरी मॉडल कैसे काम करता है।
एंड्रयू बार्बर

4

हमारे पास एक समान मुद्दा था कचरा इकट्ठा करने वाले के साथ कचरा इकट्ठा नहीं करना और स्मृति को मुक्त करना।

हमारे कार्यक्रम में, हम ओपनएक्सएमएल के साथ कुछ मामूली आकार के एक्सेल स्प्रेडशीट का प्रसंस्करण कर रहे थे। स्प्रेडशीट में 14 स्तंभों की लगभग 1000 पंक्तियों के साथ 5 से 10 "चादरें" कहीं भी शामिल थीं।

32 बिट वातावरण (x86) में प्रोग्राम "मेमोरी से बाहर" त्रुटि के साथ क्रैश होगा। हमें इसे x64 वातावरण में चलाने के लिए मिला, लेकिन हम एक बेहतर समाधान चाहते थे।

हमने एक पाया।

यहां कुछ सरलीकृत कोड टुकड़े हैं जो काम नहीं करते थे और क्या काम करते थे जब यह स्पष्ट रूप से कूड़ा उठाने वाली वस्तुओं को स्मृति से मुक्त करने के लिए गारबेज कलेक्टर को बुलाता है।

सबरूटीन के अंदर से GC को कॉल करने से काम नहीं चला। याददाश्त फिर कभी नहीं मिली ...

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
End Sub

उपखंड के दायरे से बाहर जीसी कॉल को स्थानांतरित करके, कचरा एकत्र किया गया था और मेमोरी को मुक्त कर दिया गया था।

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
End Sub

मुझे आशा है कि यह दूसरों को मदद करता है जो .NET कचरा संग्रह से निराश हैं जब यह कॉलों को अनदेखा करने के लिए प्रकट होता है GC.Collect()

पॉल स्मिथ


4

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

स्मृति हेरफेर के साथ एक पृष्ठभूमि प्रक्रिया से निपटने का मतलब है कि यह स्वयं से निपटना नहीं है, सच है। लेकिन इसका तार्किक रूप से यह मतलब नहीं है कि यह हमारे लिए सबसे अच्छा है कि हम हर परिस्थिति में खुद से न निपटें। अधिकांश मामलों के लिए GC को अनुकूलित किया गया है। लेकिन इसका तार्किक अर्थ यह नहीं है कि यह सभी मामलों में अनुकूलित है।

क्या आपने कभी एक खुले प्रश्न का उत्तर दिया है जैसे कि 'एक निश्चित उत्तर के साथ सबसे अच्छा सॉर्टिंग एल्गोरिथ्म' क्या है? यदि हां, तो GC को स्पर्श न करें। आप में से उन लोगों के लिए जिन्होंने शर्तों के लिए पूछा, या 'इस मामले में' प्रकार के उत्तर दिए, आप जीसी के बारे में जानने और इसे सक्रिय करने के लिए आगे बढ़ सकते हैं।

कहते हैं, मेरे पास क्रोम और फ़ायरफ़ॉक्स में एप्लिकेशन फ्रीज़ हैं, जो मुझे नरक से बाहर निकालते हैं, और फिर भी कुछ मामलों के लिए मेमोरी अनियंत्रित हो जाती है - यदि वे केवल कचरा कलेक्टर को कॉल करना सीखेंगे - या मुझे एक दिया बटन इतना है कि जैसे ही मैं एक पृष्ठ का पाठ पढ़ना शुरू करता हूं, मैं इसे हिट कर सकता हूं और इस तरह अगले 20 मिनट के लिए फ्रीज हो सकता हूं।


2

मुझे लगता है कि आप परिदृश्य के बारे में सही हैं, लेकिन मुझे एपीआई के बारे में निश्चित नहीं है।

Microsoft का कहना है कि ऐसे मामलों में आपको GC के लिए संकेत के रूप में मेमोरी दबाव जोड़ना चाहिए कि यह जल्द ही एक संग्रह का प्रदर्शन करे।


2
दिलचस्प है, लेकिन प्रलेखन का कहना है कि AddMemoryPressure का इस्तेमाल तब किया जाना चाहिए जब 'एक छोटी प्रबंधित वस्तु एक बड़ी मात्रा में संयुक्त राष्ट्र की स्मृति आवंटित करती है'। (जोर मेरा)
रॉबर्ट पॉलसन

2

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


1
कचरा संग्रहकर्ता की विषम प्रकृति और तथ्य यह है कि उन्होंने इस कार्यशीलता को बाहरी दुनिया के सामने उजागर किया है और मुझे लगता है कि यह कुछ ऐसा है जो उपयोगी है अगर इसका उपयोग किया जाना चाहिए। समस्या इसका उपयोग नहीं कर रही है लेकिन यह जानना कि कैसे, कहाँ और कब इसका उपयोग करना है।
ट्रेप

हर दूसरे एप्लिकेशन और उनकी मेमोरी की जरूरतों के बारे में जीसी बेहतर ज्ञान का उल्लेख नहीं करना । जीसी ओएस के साथ मेमोरी को बातचीत करता है और जैसे कि उपलब्ध भौतिक मेमोरी और मशीन पर अन्य सभी प्रक्रियाओं द्वारा प्रबंधित और अप्रबंधित है। जबकि मुझे संदेह है कि जीसी वास्तव में जानता है "जब" केस-बाय-केस "के आधार पर" इकट्ठा करने का एक अच्छा समय होता है, तो यह समग्र रूप से बेहतर रणनीति होने की संभावना है ... किसी भी एकल अनुप्रयोग। ;)
दाग

2

GC.Collect () को कॉल करने की इच्छा आमतौर पर आप कहीं और की गई गलतियों के लिए कवर करने की कोशिश कर रहे हैं!

यह बेहतर होगा यदि आप पाते हैं कि आप उस सामान को निपटाना भूल गए हैं जिसकी आपको अब आवश्यकता नहीं थी।


5
शायद एक सामान्यीकरण
मिकी

1

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


1

.NET फ्रेमवर्क को कभी भी वास्तविक समय के वातावरण में चलाने के लिए डिज़ाइन नहीं किया गया था। यदि आपको वास्तव में वास्तविक समय प्रसंस्करण की आवश्यकता है, तो आप या तो एक एम्बेडेड रियलटाइम भाषा का उपयोग करेंगे जो .NET पर आधारित नहीं है या विंडोज कंप्यूटर डिवाइस पर चलने वाले .NET कॉम्पैक्ट फ्रेमवर्क का उपयोग करें।


वह .Net माइक्रो फ्रेमवर्क का उपयोग कर सकता है, जो वास्तविक समय के वातावरण के लिए डिज़ाइन किया गया था।
ट्रॉमापॉनी

@TraumaPony: इस पृष्ठ के तल पर चार्ट की जाँच करें msdn.microsoft.com/en-us/embedded/bb278106.aspx : स्पष्ट रूप से माइक्रो फ्रेमवर्क वास्तविक समय के वातावरण के लिए डिज़ाइन नहीं किया गया था। हालाँकि, यह एम्बेडेड वातावरण (जैसे WinCE) के लिए डिज़ाइन किया गया था, लेकिन कम बिजली की आवश्यकताओं के साथ।
स्कॉट डोरमैन

1

सबसे बुरा यह होगा कि आपके कार्यक्रम को थोड़ा सा फ्रीज कर दिया जाए। इसलिए यदि आपके साथ यह ठीक है, तो करें। आमतौर पर मोटे क्लाइंट या वेब ऐप्स के लिए ज्यादातर यूजर इंटरेक्शन की जरूरत नहीं होती है।

मैंने पाया है कि कभी-कभी लंबे समय तक चलने वाले थ्रेड्स या बैच प्रोग्राम्स वाले प्रोग्रामों को आउटऑफमैमोरी अपवाद मिलेगा, भले ही वे ऑब्जेक्ट्स को ठीक से डिस्पोज कर रहे हों। मुझे याद है कि एक लाइन ऑफ बिजनेस डेटाबेस लेनदेन प्रसंस्करण था; एक मोटी क्लाइंट ऐप में बैकग्राउंड थ्रेड पर एक इंडेक्सिंग रूटीन था।

दोनों मामलों में, परिणाम सरल था: नहीं GC.Collect, मेमोरी से बाहर, लगातार; GC.Collect, निर्दोष प्रदर्शन।

मैंने कई बार स्मृति समस्याओं को हल करने की कोशिश की है, कोई फायदा नहीं हुआ। मैंने उसे निकाल लिया।

संक्षेप में, इसे तब तक न डालें जब तक आपको त्रुटियां न हों। यदि आप इसे डालते हैं और यह मेमोरी की समस्या को ठीक नहीं करता है, तो इसे वापस ले लें। रिलीज मोड में परीक्षण करना और सेब से सेब की तुलना करना याद रखें।

इसके साथ केवल चीजें गलत हो सकती हैं जब आप इसके बारे में नैतिकता प्राप्त करते हैं। यह मूल्यों का मुद्दा नहीं है; कई प्रोग्रामर मारे गए हैं और सीधे अपने कोड में कई अप्राकृतिक GC.Collects के साथ स्वर्ग चले गए हैं, जो उन्हें रेखांकित करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.