2010-04-20 11 views
16

बस दूसरे दिन मैं एक मेमोरी रिसाव की जांच कर रहा था जो ऐप को ~ 50 एमबी से ~ 130 एमबी तक दो मिनट से कम कर रहा था। यह पता चला है कि समस्या ConcurrentQueue कक्षा के साथ थी। आंतरिक रूप से, कक्षा एरे की एक लिंक्ड सूची स्टोर करता है। जब किसी आइटम को ConcurrentQueue से हटा दिया जाता है, तो सरणी में अनुक्रमणिका बंप हो जाती है, लेकिन आइटम सरणी में रहता है (यानी यह शून्य पर सेट नहीं है)। पूरे सरणी नोड को पर्याप्त एनक्यूज/डेक्यू के बाद गिरा दिया जाता है, इसलिए यह तकनीकी रूप से लीक नहीं है, लेकिन यदि ConcurrentQueue में बड़ी ऑब्जेक्ट्स डालते हैं, तो यह हाथ से तेज़ हो सकता है। दस्तावेज इस खतरे का कोई ध्यान नहीं देता है।.NET Framework - संभावित मेमोरी-लीकी कक्षाएं?

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

उत्तर

0

हालांकि प्रत्यक्ष स्मृति रिसाव या .NET/BCL के लिए विशिष्ट नहीं है, स्ट्रिंग concatenation (+ = ऑपरेटर का उपयोग कर) मुद्दा है। भारी कचरा इकट्ठा करने के कारण यह लूप में सुंदर सीपीयू गहन है।

+0

हाँ। जावा ने इसे स्ट्रिंगबिल्डर का उपयोग करने के लिए परिवर्तित करके हल किया; मुझे नहीं पता कि .NET ने ऐसा क्यों नहीं किया है। –

+0

.NET के पास यह सिस्टम के नीचे है। टेक्स्ट – Aren

+2

वीएस सी # कंपाइलर स्ट्रिंगबिल्डर में आंतरिक रूप से अभिव्यक्तियों को परिवर्तित करने के लिए पर्याप्त स्मार्ट है ("यह" + "" + "स्ट्रिंग #" + स्ट्रिंग नम्बर) आंतरिक रूप से स्ट्रिंगबिल्डर में है, अगर यह समझ में आता है ऐसा करने के लिए। –

11

आप सही हैं। बग विधि System.Collections.Concurrent.ConcurrentQueue<T>+Segment.TryRemove(out T, ref ConcurrentQueue<T>.Segment) में स्थित है।

आप परावर्तक में इस विधि को देखें, तो आप निम्न पंक्ति देखेंगे:

result = this.m_array[low]; 

यह बाद निम्न पंक्ति होनी चाहिए:

this.m_array[low] = default(T); 

संदर्भ के लिए, आप देख सकते हैं विधि System.Collections.Generic.Queue<T>.Dequeue() विधि में यह सही ढंग से कार्यान्वित कैसे किया जाता है।

+0

यूप; इसे परावर्तक में भी देखा, हालांकि मुझे यकीन नहीं है कि टी किसी तरह से परमाणु/थ्रेडिंग तोड़ देगा? –

+1

नहीं, यह निश्चित रूप से एक बग है। बाल्टी उस क्षेत्र में संरक्षित है, और कोड यह सुनिश्चित करने के लिए डिज़ाइन किया गया है कि इसमें शामिल मूल्य केवल एक बार पढ़ा जाता है। –

+1

बीटीडब्लू, मैंने मूल रूप से अप्रैल में एमएस में किसी को इस पर एक रिपोर्ट भेजी थी। 1. मुझे नहीं लगता कि उन्हें अभी तक इसे ठीक करने का मौका मिला है। दुर्भाग्यवश, जब तक समस्या हल नहीं हो जाती है तब तक कक्षा पूरी तरह से अनुपयोगी होती है। –

-1

ConcurrentQueue केवल अधिकतम 31 अस्वीकृत वस्तुओं को रखेगा। यह एक बड़ी समस्या नहीं पेश करनी चाहिए जबतक कि आप वास्तव में बड़े ऑब्जेक्ट ग्राफ़ से निपट नहीं रहे हैं।

वैसे भी, यह भावना एक ConcurrentQueue का उपयोग कर आप 32 वस्तुओं के आवंटन के लिए enought स्थान नहीं है अगर नहीं है ...

+0

क्या होगा यदि मुझे संदेश कतार मिली है? क्या होगा यदि यह सर्वर सॉकेट के क्लाइंट कनेक्शन के लिए है, तो 500 ऐसी कतार है? और प्रत्येक ग्राहक मुझे 10 10 लंबे समय तक 32 संदेश भेजने का फैसला करता है। मैं 160 एमबी कचरा के साथ समाप्त होता हूं। और अगर मेरे पास 2000 ऐसे क्लाइंट हैं, या संदेश बड़े हो गए हैं, तो मैं आउटऑफमेमरी अपवाद और प्रोग्राम क्रैश प्राप्त कर रहा हूं। और हे, अगर मैं इस शर्मीली कतारों का पुन: उपयोग करने की कोशिश करता हूं, और उनमें से पहले से आवंटित करने का प्रयास करता हूं, तो मुझे सॉकेट कनेक्शन बंद होने के बाद भी यह कचरा याद आया है। जाहिर है, यह कतार का उपयोग करने के लिए समझ में आता है, जब यह रिसाव नहीं करता है। – Gman