2009-11-05 12 views
6

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

HandleCount: 277 
NonpagedSystemMemorySize: 48136 
PagedMemorySize: 1898590208 
PagedSystemMemorySize: 189036 
PeakPagedMemorySize: 1938321408 
VirtualMemorySize: 2016473088 
PeakVirtualMemory: 2053062656 
WorkingSet: 177774592 
PeakWorkingSet: 883834880 
PrivateMemorySize: 1898590208 
PriviligedProcessorTime: 00:00:15.8593750 
UserProcessorTime: 00:00:01.6562500 
TotalProcessorTime: 00:00:17.5156250 
GDI Objects: 30 
User Objects: 27 

मैं एक स्वचालित वैश्विक अपवाद पकड़ने वाला है कि अपवाद पर उपरोक्त जानकारी (System.Diagnostics.Process का प्रयोग करके) बटोरता है - अपवाद जानकारी के साथ, लॉग इन करें और एक स्क्रीन शॉट - और सब कुछ ई मेल मुझे।

यह अच्छी तरह से काम कर रहा है क्योंकि मैं ई-मेल की गई जानकारी के आधार पर बग प्लग करने में सक्षम हूं। यह अब तक है। सॉफ्टवेयर हजारों लाइनों का है और प्रबंधित और अप्रबंधित संसाधनों का उपयोग करता है।

मैं लाइन के माध्यम से कोड के माध्यम से जा रहा शुरू कर सकता हूं, लेकिन कुछ मुझे कैसे लगता है कि यह मेमोरी बिल्ड-अप समस्या को कम करने का प्रयास करने का सबसे अच्छा तरीका नहीं हो सकता है।

जैसा कि मैंने पहले कभी इस तरह के विश्लेषण नहीं किया है, आप इस तरह की समस्या से संपर्क करने का सुझाव कैसे देंगे?

उत्तर

2

इसमें डीबगर संलग्न करें और त्रुटि को पुन: उत्पन्न करें। अपवाद समय पर कॉल स्टैक आपको बताएगा कि त्रुटि कहां है।

या तो आप एक स्मृति रिसाव (रों), तो आप अपने वस्तुओं के निपटान नहीं कर रहे है, या आप बेहतर हार्डवेयर :)

+0

आईएमएचओ, इस मामले में डीबगर का उपयोग करके अपवाद को पकड़ना बेकार होगा, नुकसान (शायद सबसे अधिक स्मृति स्मृति रिसाव) कहीं और किया जा चुका है। – Naveen

+0

बस कुछ विकल्प फेंकना। देखने के लिए चोट नहीं पहुंचा सकता है। – tsilb

+0

tslib का एक बिंदु है, कभी-कभी आप स्मृति से बाहर होने पर संकुचित हो सकते हैं। – Gregory

9

पास कुछ विकल्प होते हैं की जरूरत है। RedGate से ANTS Memory Profiler जैसे समर्पित मेमोरी प्रोफाइलर्स इस तरह की समस्या का निवारण करने के लिए बहुत उपयोगी हो सकते हैं।

यदि आप एक समर्पित उपकरण पर पैसा खर्च नहीं करना चाहते हैं, तो आप WinDbg (Debugging tools for Windows का हिस्सा, माइक्रोसॉफ्ट से मुफ्त डाउनलोड) का भी उपयोग कर सकते हैं। यह आपको प्रबंधित ढेर, विभिन्न ऐपडोमेन ढेर और आगे के लिए ढेर उपयोग दिखा सकता है।

WinDbg का उपयोग करने पर संकेतों के लिए this blog पर एक नज़र डालें।

ध्यान रखें कि स्मृति से समस्या निवारण कठिन हो सकता है, क्योंकि आप आमतौर पर वास्तविक समस्या नहीं देखते हैं बल्कि केवल एक लक्षण देखते हैं। तो एक दुर्घटना के विपरीत जहां कॉल स्टैक आपको समस्या के स्रोत का एक बहुत अच्छा संकेत देगा, ओओएम के साथ एक प्रक्रिया के लिए कॉल स्टैक बहुत कम प्रकट हो सकता है।

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

+0

+1! – tijmenvdk

+0

+1 कुछ उपयोगी पोस्ट करने के लिए। – Gregory

+0

एएनटीएस, महान उपकरण। – BennyM

3

.NET अनुप्रयोगों में मेमोरी लीक का पता लगाने के बारे में इस MSDN आलेख पर एक नज़र डालें।

शायद आपके पास कुछ समस्याएं हैं जहां स्मृति आवंटित की जा रही है और कभी एकत्र नहीं की जाती है।

1

आपकी पीकवर्किंगसेट सामान्य संख्या इंगित करता है जब 32 बिट सीएलआर बमबारी शुरू होता है।

जो लोग आपको बताते हैं, और स्वचालित स्मृति प्रबंधन के विशाल विडंबना के बावजूद, आपको इसके बारे में पता होना चाहिए और यह सुनिश्चित करना होगा कि आप इस तरह के/32 बिट सिस्टम पर उस सीमा तक कभी भी संपर्क न करें। बहुत से लोग इससे अनजान हैं और मैं आमतौर पर अपने सी # ब्लोट डाउनवॉट्स को चुनना पसंद करता हूं, लेकिन जब आप एक ऐसे डेस्कटॉप पर ऐसे कुछ ऐप्स चलाते हैं तो आप कुछ विनाश की उम्मीद कर सकते हैं।बस वीएस शट डाउन के प्रबंधित हिस्से को देखें, यह एक पीसी के माध्यम से चल रही ट्रेन की तरह है।

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

और इन दिनों आकार में एक c880MB डेटासेट दयनीय है .. तथ्य!

10

[भेड़ सी # 3.0 के लिए टुकड़ा] हम उस के लिए एक उपकरण प्रदान करते हैं।

http://msdn.microsoft.com/en-us/library/ms979205.aspx

CLR प्रोफाइलर आप एक प्रक्रिया का प्रबंधित ढेर और को देखने के लिए कचरा कलेक्टर के व्यवहार की जांच सक्षम बनाता है। टूल में विभिन्न विचारों का उपयोग करके, आप निष्पादन, आवंटन और स्मृति आपके आवेदन की खपत के बारे में उपयोगी जानकारी प्राप्त कर सकते हैं।

CLR प्रोफाइलर का उपयोग करके आप कोड है कि बहुत ज्यादा स्मृति आबंटित करता है, भी कई कचरा संग्रह का कारण बनता है, और लंबे समय के लिए स्मृति को पकड़ की पहचान कर सकते हैं।

0

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

2

मेरे पास बिल्कुल वही एप्लिकेशन है। :) हमारे आवेदन का उपयोग 10 जीबी रैम तक करने के लिए किया जाता है। यह स्पष्ट रूप से बुरा है। कुछ अनुकूलन के बाद मैंने लगभग 50 गुना मेमोरी उपयोग कम करने में कामयाब रहा, इसलिए अब एक ही डेटा सेट 200 एमबी तक ले जाता है। जादू? नहीं :) मैंने क्या किया:

  1. कुछ डेटा स्मृति में कई बार संग्रहीत किया गया था (कई प्रतियां)। मैंने डेटा के प्रत्येक गुच्छा की एक प्रति बना दी।
  2. कुछ डेटा string के रूप में संग्रहीत किया गया था, लेकिन अधिक कुशल तरीका int है क्योंकि उन तारों में केवल अंक थे।
  3. मुख्य डेटा भंडारण वर्ग था। We wrote our own dictionary जो किसी भी हैश को स्टोर नहीं करता है - परिणामस्वरूप स्मृति उपयोग 64 बिट सिस्टम पर 3 गुना कम हो गया है, और 32 बिट सिस्टम पर 2 बार।

तो मेरा सवाल है: डेटा स्टोर करने के लिए आप मुख्य कक्षा/वस्तु का उपयोग करते हैं? आप किस प्रकार का डेटा स्टोर करते हैं?

0

बहुत से उपयोगी समाधान पहले से ही सुझाए गए हैं और एमएसडीएन लेख बहुत गहन है। ऊपर दिए गए सुझावों के साथ मैं निम्नलिखित भी करूँगा;

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

क्या स्मृति उपयोग अपवाद से पहले लंबे समय तक धीरे-धीरे बढ़ता है (उदाहरण के लिए एक सर्वर प्रक्रिया जो अनिश्चित काल तक चलती है) या क्या यह अपवाद तक काफी तेजी से बढ़ जाती है?क्या बहुत सारे धागे चल रहे हैं या सिर्फ एक?

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

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

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

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

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

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

संबंधित मुद्दे