2013-02-22 22 views
12

में निहित सी # शब्दकोश से स्मृति को हटा दें मुझे डब्ल्यूसीएफ वेब सेवा (कुछ डंप, मेमोरी लीक इत्यादि) के साथ कुछ समस्याएं थीं और मैं एक प्रोफाइलिंग टूल (एएनटीएस मेमोरी प्रोफाइल) चलाता हूं।एक स्थिर वस्तु

बस यह पता लगाने के लिए कि प्रसंस्करण के साथ (मैं एक विशिष्ट परीक्षण चलाता हूं और फिर बंद कर देता हूं), जेनरेशन 2 वेब सेवा के लिए स्मृति का 25% है। मैंने इस मेमोरी को ट्रैक करने के लिए ट्रैक किया कि मेरे पास एक हैश ऑब्जेक्ट था (शून्य, शून्य) आइटम, -1 हैश कोड के साथ।

वेब सेवा का वर्कफ़्लो तात्पर्य है कि विशिष्ट प्रसंस्करण वस्तुओं को जोड़ा जाता है और फिर शब्दकोश से हटा दिया जाता है (केवल सरल Add और Remove)। कोई बड़ी बात नहीं। लेकिन ऐसा लगता है कि सभी वस्तुओं को हटा दिए जाने के बाद, शब्दकोश (शून्य, शून्य) KeyValuePair एस से भरा हुआ है। वास्तव में उनमें से हजारों, जैसे कि वे स्मृति का एक बड़ा हिस्सा लेते हैं और अंततः एक अतिप्रवाह होता है, इसी तरह के मजबूर अनुप्रयोग पूल रीसायकल और डीडब्ल्यू 20.एक्सई को सभी सीपीयू चक्र मिलते हैं।

शब्दकोश वास्तव में Dictionary<SomeKeyType, IEnumerable<KeyValuePair<SomeOtherKeyType, SomeCustomType>>> (System.OutOfMemoryException because of Large Dictionary) है इसलिए मैंने पहले ही जांच की है कि कुछ प्रकार की संदर्भ होल्डिंग चीजें हैं।

शब्दकोष एक स्थिर वस्तु (इसे प्रोसेसिंग के माध्यम से विभिन्न प्रसंस्करण धागे के लिए एक्सेसिबल बनाने के लिए) में निहित है, इसलिए इस प्रश्न से और कई और (Do static members ever get garbage collected?) मुझे समझ में आता है कि यह शब्दकोश जनरेशन 2 में क्यों है। लेकिन यह भी कारण है उनमें से (शून्य, शून्य)? यहां तक ​​कि अगर मैं शब्दकोश से वस्तुओं को हटा देता हूं तो भी स्मृति में हमेशा कब्जा कर लिया जाएगा?

यह इस प्रश्न में Deallocate memory from large data structures in C# की गति गति नहीं है। ऐसा लगता है कि स्मृति कभी पुनः प्राप्त नहीं की जाती है।

क्या कुछ ऐसा है जो मैं वास्तव में शब्दकोश से वस्तुओं को हटाने के लिए कर सकता हूं, न केवल इसे (शून्य, शून्य) जोड़े के साथ भरना? क्या मुझे कुछ और जांचने की ज़रूरत है?

+0

+ !: उचित शोध करने और एक अच्छा प्रश्न लिखने के लिए। – Virtlink

+1

'सूची <> 'में' TrimExcess() 'विधि है,' शब्दकोश <,> दुर्भाग्यवश नहीं है। सोचा यह एक आसान स्कोर था :) –

+0

शब्दकोश कॉलिंग करता है। क्लीयर() कोई फर्क पड़ता है? – Alex

उत्तर

9

शब्दकोश हैश तालिका में स्टोर स्टोर आइटम। इस के लिए आंतरिक रूप से एक सरणी का उपयोग किया जाता है। हैश टेबल काम करने के तरीके के कारण, यह सरणी हमेशा संग्रहित वस्तुओं की वास्तविक संख्या (कम से कम 30% बड़ी) से बड़ी होनी चाहिए। माइक्रोसॉफ्ट 72% के लोड फैक्टर का उपयोग करता है, यानी सरणी का कम से कम 28% खाली होगा (An Extensive Examination of Data Structures Using C# 2.0 और विशेष रूप से The System.Collections.Hashtable Class और The System.Collections.Generic.Dictionary Class) इसलिए शून्य/शून्य प्रविष्टियां केवल इस खाली स्थान का प्रतिनिधित्व कर सकती हैं।

यदि सरणी बहुत छोटी है, तो यह स्वचालित रूप से बढ़ेगी; हालांकि, जब वस्तुओं को हटा दिया जाता है, तो सरणी कम नहीं होती है, लेकिन जब खाली वस्तुओं को सम्मिलित किया जाता है तो उसे मुक्त किया जाना चाहिए।

आप इस शब्दकोश के नियंत्रण में हैं, तो आप इसे छोटा करने के लिए सेवा को पुन: बनाने की कोशिश कर सकते हैं:

theDict = new Dictionary<TKey, IEnumerable<KeyValuePair<TKey2, TVal>>>(theDict); 

लेकिन समस्या यह वास्तविक (गैर खाली) प्रविष्टियों से पैदा हो सकता है। आपका शब्दकोश स्थिर है और इसलिए कचरा कलेक्टर द्वारा स्वचालित रूप से पुनः दावा नहीं किया जाएगा, जब तक कि आप इसे एक और शब्दकोश या null (theDict = new ... या theDict = null) असाइन न करें।यह केवल शब्दकोश के लिए ही सही है जो स्थिर है, इसकी प्रविष्टियों के लिए नहीं। जब तक हटाए गए प्रविष्टियों के संदर्भ कहीं और मौजूद होते हैं, तब तक वे बने रहेंगे। जीसी किसी ऑब्जेक्ट (पहले या बाद में) को पुनः प्राप्त करेगा जिसे किसी संदर्भ के माध्यम से और अधिक नहीं पहुंचा जा सकता है। इससे कोई फर्क नहीं पड़ता है, चाहे इस ऑब्जेक्ट को स्थैतिक घोषित किया गया हो या नहीं। वस्तुएं स्वयं स्थिर नहीं हैं, केवल उनके संदर्भ हैं।

+0

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

+0

@ ओलिवियर यह कहकर कि आइटम हटा दिए जाने पर यह कम नहीं होता है, क्या इसका मतलब यह है कि स्मृति का अभी भी उपयोग किया जाएगा? –

+0

@ सिरराज मंसूर: हाँ। –

4

ऐसा लगता है कि आपको समय-समय पर उस समय में अंतरिक्ष को रीसायकल करने की आवश्यकता है। आप इसे नया बनाकर कर सकते हैं: new Dictionary<a,b>(oldDict)। थ्रेड-सुरक्षित तरीके से ऐसा करना सुनिश्चित करें।

यह कब करना है? या तो टाइमर (60sec?) के टिक पर या जब एक विशिष्ट संख्या में लिखने के लिए (100k?) (आपको एक संशोधन काउंटर रखना होगा)।

0

एक समाधान स्थिर शब्दकोश पर Clear() विधि को कॉल करने के लिए किया जा सकता है। इस तरह, शब्दकोश का संदर्भ उपलब्ध रहेगा, लेकिन निहित वस्तुओं को जारी किया जाएगा।

+0

किसी ने टिप्पणी में इसका उल्लेख किया, और मैंने उस समय उत्तर दिया कि 'साफ़' विधि का उपयोग करने से मैं जो चाहता हूं वह नहीं बढ़ रहा था। –

-2

यह कुछ समय पहले एक डीबी ऐप में बड़ी डेटाटेबल ऑब्जेक्ट्स से निपटने के दौरान मिले एक मुद्दे के समान है। बस डेटाटेबल पर साफ़ कॉलिंग शून्य पंक्तियों के साथ स्मृति में सभी पंक्तियों को छोड़ रहा था। नई खाली, स्वच्छ, DataTable में वापस

someTable.Clear(); 
someTable.Dispose(); 
someTeble = new DataTable()... 
सही स्तंभ जोड़ने का अतिरिक्त कदम के साथ

: तो हम जैसा कोई विशेष समाशोधन पद्धति लागू।

इस में अभिशाप था कि हमारे पास कुछ कोड संदर्भित कोड था जो निपटान कर रहा था और कोड नए उदाहरण को इंगित नहीं कर रहा था। बड़ी गड़बड़।

मेरा अनुमान है कि हुड के नीचे ये उनके ऊपर एक .net wrapper के साथ अप्रबंधित वस्तुएं हैं और स्मृति केवल तभी जारी की जाती है जब मुख्य वस्तु नष्ट हो जाती है।

तो यदि आप उन्हें गतिशील तरीके से उपयोग कर रहे हैं तो आपको स्मृति को स्वयं साफ करना होगा।

मैं बस उस पोस्ट में भाग गया क्योंकि मुझे हैशटेबल्स के साथ एक ही समस्या दिखाई दे रही है।

+0

यह सवाल का जवाब नहीं देता है – Liam

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