.NET में मेमोरी लीक खोजने के लिए कौन सी रणनीतियाँ और उपकरण उपयोगी हैं?


152

मैंने 10 साल तक C ++ लिखा। मुझे स्मृति समस्याओं का सामना करना पड़ा, लेकिन उन्हें उचित मात्रा में प्रयास के साथ तय किया जा सकता है।

पिछले कुछ वर्षों से मैं C # लिख रहा हूं। मुझे लगता है कि मुझे अभी भी बहुत सारी स्मृति समस्याएं हैं। वे गैर-निर्धारण के कारण निदान और ठीक करना मुश्किल हैं, और क्योंकि C # दर्शन यह है कि आपको ऐसी चीजों के बारे में चिंता नहीं करनी चाहिए जब आप बहुत निश्चित रूप से करते हैं।

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

.NET में मेमोरी लीक से निपटने के लिए किस तरह की रणनीति और उपकरण उपयोगी हैं?


आपकी पोस्ट का शीर्षक वास्तव में आपकी पोस्ट के प्रश्न से मेल नहीं खाता है। मेरा सुझाव है कि आप अपना शीर्षक अपडेट करें।
केविन

आप सही हे। क्षमा करें, मैं उस मौजूदा रिसाव से थोड़ा तंग आ रहा था जिसका मैं शिकार हूँ! शीर्षक अपडेट किया गया।
स्कॉट लैंगहम

3
@ स्थिति: .NET से तंग मत आना, यह समस्या नहीं है। आपका कोड है
GEOCHET

3
हां, मेरा कोड, या तीसरे पक्ष के पुस्तकालयों में मुझे उपयोग करने की खुशी है।
स्कॉट लैंगहम

@ उत्तर: मेरा उत्तर देखें। मेम्प्रोफाइलर इसके लायक है। इसका उपयोग करने से आपको .NET GC दुनिया को समझने का एक नया स्तर मिलेगा।
15

जवाबों:


51

जब मैं मेमोरी लीक होने का संदेह करता हूं तो मैं स्किटेक के मेमोफिलर का उपयोग करता हूं।

अब तक, मैंने इसे बहुत विश्वसनीय और शक्तिशाली पाया है। इसने कम से कम एक मौके पर मेरी बेकन को बचाया है।

.NET IMO में GC बहुत अच्छी तरह से काम करता है, लेकिन किसी अन्य भाषा या मंच की तरह, यदि आप खराब कोड लिखते हैं, तो खराब चीजें होती हैं।


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

1
मैंने इसे उत्तर के रूप में स्वीकार कर लिया है क्योंकि इसके लिए मेरे लिए क्या काम किया गया था, लेकिन मुझे लगता है कि अन्य सभी उत्तर बहुत उपयोगी हैं। वैसे, इस टूल को आमतौर पर SciTech's Mem Profiler कहा जाता है!
स्कॉट लैंगहम

41

बस भूलने की समस्या के लिए, इस ब्लॉग पोस्ट में वर्णित समाधान का प्रयास करें । यहाँ सार है:

    public void Dispose ()
    {
        // Dispose logic here ...

        // It's a bad error if someone forgets to call Dispose,
        // so in Debug builds, we put a finalizer in to detect
        // the error. If Dispose is called, we suppress the
        // finalizer.
#if DEBUG
        GC.SuppressFinalize(this);
#endif
    }

#if DEBUG
    ~TimedLock()
    {
        // If this finalizer runs, someone somewhere failed to
        // call Dispose, which means we've failed to leave
        // a monitor!
        System.Diagnostics.Debug.Fail("Undisposed lock");
    }
#endif

मैं डिबग के बजाय एक अपवाद फेंकना पसंद करूंगा। जेल
पेड्रो77

17

हमने अपनी परियोजना में रेड गेट सॉफ्टवेयर द्वारा चींटियों के प्रो प्रो का उपयोग किया है । यह सभी .NET भाषा-आधारित अनुप्रयोगों के लिए वास्तव में अच्छी तरह से काम करता है।

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

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

class ParentObject
   Private mRelatedObject as New CRelatedObject
   public Readonly property RelatedObject() as CRelatedObject
      get
         mRelatedObject.getWithID(RelatedObjectID)
         return mRelatedObject
      end get
   end property
End class

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

class ParentObject
   Private mRelatedObject as CRelatedObject
   Public ReadOnly Property RelatedObject() as CRelatedObject
      Get
         If mRelatedObject is Nothing
            mRelatedObject = New CRelatedObject
         End If
         If mRelatedObject.isEmptyObject
            mRelatedObject.getWithID(RelatedObjectID)
         End If
         return mRelatedObject
      end get
   end Property
end class

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


मैं इस उत्पाद को दूसरा। यह सबसे अच्छा प्रोफाइलरों में से एक था जिसका मैंने उपयोग किया है।
गॉर्ड सेप

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

ठीक है, नया संस्करण 5.1, बहुत बेहतर की एक बिल्ली है। लीक के कारण का पता लगाने में आपकी मदद करने में बेहतर है (हालांकि - अभी भी इसके साथ कुछ समस्याएं हैं जो ANTS ने मुझे बताया है कि वे अगले संस्करण में ठीक करेंगे)। हालांकि, अब भी अप्रबंधित कोड नहीं है, लेकिन अगर आप अनवांटेड कोड के बारे में परेशान नहीं हैं, तो यह अब बहुत अच्छा उपकरण है।
स्कॉट लंघम

7

आपको तब भी मेमोरी के बारे में चिंता करने की ज़रूरत है जब आप प्रबंधित कोड लिख रहे हैं जब तक कि आपका आवेदन तुच्छ न हो। मैं दो चीजों का सुझाव दूंगा: पहला, C # के माध्यम से CLR पढ़ें क्योंकि यह आपको .NET में मेमोरी मैनेजमेंट को समझने में मदद करेगा। दूसरा, CLRProfiler (Microsoft) जैसे उपकरण का उपयोग करना सीखें । इससे आपको अंदाजा हो सकता है कि आपकी मेमोरी लीक का कारण क्या है (जैसे कि आप अपने बड़े ऑब्जेक्ट हीप विखंडन पर एक नज़र डाल सकते हैं)


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

6

क्या आप अनवांटेड कोड का उपयोग कर रहे हैं? यदि आप Microsoft से अप्रबंधित कोड का उपयोग नहीं कर रहे हैं, तो पारंपरिक अर्थों में मेमोरी लीक संभव नहीं है।

एक अनुप्रयोग द्वारा उपयोग की जाने वाली मेमोरी को हालांकि जारी नहीं किया जा सकता है, इसलिए एक आवेदन की मेमोरी आवंटन आवेदन के पूरे जीवन में बढ़ सकता है।

से कैसे Microsoft.com पर आम भाषा क्रम में मेमोरी लीक पहचान करने के लिए

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

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

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

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


5
ब्लॉगs.msdn.com/tess/archive/2006/01/23/… देखें । यह वास्तव में कोई फर्क नहीं पड़ता कि स्मृति रिसाव "पारंपरिक" है या नहीं, यह अभी भी एक रिसाव है।
कांस्टेंटिन

2
मैं आपकी बात देख रहा हूं - लेकिन एक कार्यक्रम के द्वारा स्मृति का अकुशल आवंटन और पुन: उपयोग स्मृति रिसाव से अलग है।
टिमोथी ली रसेल

अच्छा जवाब, मुझे याद रखने के लिए धन्यवाद कि इवेंट हैंडलर खतरनाक हो सकते हैं।
frameworkninja

3
@ टिमोथी ली रसेल: यदि स्मृति की एक अनबाउंड (1) राशि एक साथ आवंटित (रूटेड) रह सकती है, तो बेकार (2) होने के बाद, सिस्टम में कुछ भी जानकारी और आवेग के बिना इसे समय पर अंजाम देने के लिए आवश्यक है, यह एक स्मृति रिसाव है । यहां तक ​​कि अगर किसी दिन स्मृति मुक्त हो सकती है, अगर ऐसा होने से पहले सिस्टम को चोक करने के लिए पर्याप्त बेकार सामान जमा हो सकता है, तो यह एक रिसाव है। (1) O (N) से अधिक, N उपयोगी आवंटन की राशि है; (2) सामग्री बेकार है यदि इसके संदर्भ को हटाने से कार्यक्रम की कार्यक्षमता प्रभावित नहीं होगी।
सुपरकैट

2
@ टिमोथी ली रसेल: सामान्य "मेमोरी लीक" पैटर्न तब होता है जब मेमोरी को एक इकाई द्वारा किसी अन्य इकाई की ओर से आयोजित किया जाता है , यह उम्मीद की जाती है कि जब इसकी आवश्यकता नहीं होगी, लेकिन बाद वाला पहले को बताए बिना इकाई को छोड़ देता है। मेमोरी रखने वाली इकाई को वास्तव में इसकी आवश्यकता नहीं है, लेकिन यह निर्धारित करने का कोई तरीका नहीं है।
सुपरकैट

5

सभी प्रकारों की मेमोरी लीक को ट्रैक करने के लिए विंडबग और अन्य टूल का उपयोग करके इस ब्लॉग में वास्तव में कुछ अद्भुत वाकथ्रू हैं। अपने कौशल को विकसित करने के लिए उत्कृष्ट रीडिंग।


5

मुझे विंडोज़ सेवा में बस एक मेमोरी लीक थी, जिसे मैंने ठीक किया।

सबसे पहले, मैंने मेमप्रोफाइलर की कोशिश की । मुझे वास्तव में उपयोग करने में मुश्किल हुई और उपयोगकर्ता के अनुकूल नहीं।

फिर, मैंने जस्टट्रेस का उपयोग किया जो उपयोग करने में आसान है और आपको उन वस्तुओं के बारे में अधिक विवरण देता है जो सही ढंग से निपटाए नहीं गए हैं।

इसने मुझे मेमोरी लीक को वास्तव में आसानी से हल करने की अनुमति दी।


3

यदि आप जो लीक देख रहे हैं, वह एक भगोड़ा कैश कार्यान्वयन के कारण है, तो यह एक ऐसा परिदृश्य है, जिसमें आप WeakReference के उपयोग पर विचार करना चाह सकते हैं। यह सुनिश्चित करने में मदद कर सकता है कि स्मृति को आवश्यक होने पर जारी किया जाए।

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


3

मैं Jetbrains से डॉटमोरी पसंद करता हूं


आप केवल एक ही हो सकते हैं :)
हेलबाई

मैंने इसे भी आजमाया। मुझे लगता है कि यह एक अच्छा उपकरण है। उपयोग करने में आसान, सूचनात्मक। दृश्य स्टूडियो के लिए एकीकृत
रेड आई

हमारे मामले में, जब मेमोरी लीक की समस्या निवारण के लिए, दृश्य स्टूडियो स्नैपशॉट उपकरण क्रैश हो गया / स्नैपशॉट नहीं आया। Dotmemory ने अपना कूल रखा और 3 + GB के कई स्नैपशॉट को (आसानी से) सहजता से संभाला।
माइकल कार्गल

3

बड़ी बंदूकें - विंडोज के लिए डिबगिंग टूल

यह उपकरणों का एक अद्भुत संग्रह है। आप इसके साथ प्रबंधित और अप्रबंधित दोनों प्रकार के विश्लेषण कर सकते हैं और आप इसे ऑफ़लाइन कर सकते हैं। यह हमारे ASP.NET अनुप्रयोगों में से एक को डीबग करने के लिए बहुत आसान था जो कि मेमोरी के अधिक उपयोग के कारण पुनर्चक्रण करता रहा। मुझे केवल उत्पादन सर्वर पर चलने वाली प्रक्रिया की पूर्ण मेमोरी डंप बनाना था, सभी विश्लेषण WinDbg में ऑफ़लाइन किया गया था। (यह याद दिलाया गया कि कुछ डेवलपर मेमोरी सेशन स्टोरेज में ज्यादा इस्तेमाल कर रहे हैं।)

"अगर यह टूट गया है ..." ब्लॉग पर इस विषय पर बहुत उपयोगी लेख हैं।


2

सबसे अच्छी बात यह है कि अपनी वस्तुओं के संदर्भों का ध्यान रखें। जिन वस्तुओं के बारे में आपको कोई परवाह नहीं है, उन्हें हैंगिंग रेफरेंस के साथ समाप्त करना बहुत आसान है। यदि आप अब कुछ भी उपयोग नहीं करने जा रहे हैं, तो इससे छुटकारा पाएं।

स्लाइडिंग एक्सपीरिएंस के साथ कैश प्रोवाइडर का उपयोग करने की आदत डालें, ताकि अगर किसी वांछित समय विंडो के लिए संदर्भित न हो तो यह डीएफ़ेरिफ़ाइड और क्लीन अप हो जाता है। लेकिन अगर इसे बहुत एक्सेस किया जा रहा है तो यह मेमोरी में कहेगा।


2

सबसे अच्छा उपकरणों में से एक का उपयोग कर रहा Windows के लिए डीबगिंग उपकरण , और का उपयोग कर प्रक्रिया का एक स्मृति डम्प लेने adplus , तो का उपयोग windbg और एसओएस प्रक्रिया स्मृति, धागे, और कॉल के ढेर का विश्लेषण करने के प्लगइन।

आप सर्वर पर समस्याओं की पहचान करने के लिए भी इस पद्धति का उपयोग कर सकते हैं, उपकरण स्थापित करने के बाद, निर्देशिका साझा करें, फिर सर्वर से शेयर से कनेक्ट करें (नेट उपयोग) और या तो क्रैश या हैंग प्रक्रिया का डंप लें।

फिर ऑफ़लाइन विश्लेषण करें।


हां, यह अच्छी तरह से काम करता है, विशेष रूप से अधिक उन्नत सामान या जारी किए गए सॉफ़्टवेयर में समस्याओं का निदान करने के लिए जिन्हें आप आसानी से डिबगर संलग्न नहीं कर सकते हैं। इस ब्लॉग में इन उपकरणों का अच्छी तरह से उपयोग करने के लिए बहुत सारे सुझाव दिए गए हैं: blogs.msdn.com/tess
Scott Langham

2

प्रबंधित एप्लिकेशन के लिए मेरे एक सुधार के बाद मेरे पास एक ही बात थी, जैसे कि कैसे सत्यापित करें कि मेरे आवेदन में मेरे अगले बदलाव के बाद एक ही मेमोरी लीक नहीं होगी, इसलिए मैंने ऑब्जेक्ट रिलीज़ वेरिफिकेशन फ्रेमवर्क की तरह कुछ लिखा है, कृपया एक नज़र डालें NuGet पैकेज ObjectReleaseVerification । आप यहाँ एक नमूना पा सकते हैं https://github.com/outcoldman/OutcoldSolutions-ObjectReleaseVerification-Sample , और इस नमूने के बारे में जानकारी http://outcoldman.ru/en/blog/show/322


0

दृश्य स्टूडियो 2015 से मेमोरी उपयोग डेटा एकत्र करने और उसका विश्लेषण करने के लिए मेमोरी मेमोरी डायग्नोस्टिक टूल से बाहर का उपयोग करने पर विचार करें ।

मेमोरी उपयोग उपकरण आपको ऑब्जेक्ट प्रकारों के मेमोरी उपयोग प्रभाव को समझने में मदद करने के लिए प्रबंधित और देशी मेमोरी हीप के एक या अधिक स्नैपशॉट लेने देता है।


0

सबसे अच्छे साधनों में से एक, जिसका मैंने अपने DotMemory.you में उपयोग किया था, इस टूल का उपयोग VS. एक्सटेंशन के रूप में कर सकते हैं। अपने ऐप को चलाने के बाद आप मेमोरी के प्रत्येक भाग (ऑब्जेक्ट, नेमस्पेस, इत्यादि) का विश्लेषण कर सकते हैं, जो आपके ऐप का उपयोग करते हैं और उस का कुछ स्नैपशॉट लेते हैं। , अन्य स्नैपशॉट के साथ तुलना करें। DotMemory

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