2013-02-22 80 views
7

मेरे पास कुछ ऑब्जेक्ट्स हैं जो फ़ाइल पढ़ती हैं, डेटा को सरणी में सहेजती हैं और कुछ ऑपरेशन करती हैं। अनुक्रम ऑब्जेक्ट ए बनाएं, ऑब्जेक्ट ए के साथ काम करें ऑब्जेक्ट बी बनाएं, ऑब्जेक्ट बी के साथ काम करें ... प्रत्येक ऑब्जेक्ट द्वारा पढ़ा गया डेटा लगभग 10 एमबी हो सकता है। इसलिए सबसे अच्छा विकल्प प्रत्येक ऑब्जेक्ट को प्रत्येक के साथ संचालित करने के बाद हटाना होगा। मान लीजिए मैं स्मृति में लगभग 10 एमबी आवंटित करने के लिए मेरा कार्यक्रम, नहीं 10 एमबी * 1000 वस्तुओं = 1GBवस्तुओं को हटाने की आवश्यकता है: किसी फ़ंक्शन में ऑब्जेक्ट्स को डिस्प्ले या बनाएं?

वस्तुओं चाहते हैं की तरह कुछ:

class MyClass 
{ 
    List<string[]> data; 

    public MyClass(string datafile) 
    { 
     using (CsvReader csv = new CsvReader(new StreamReader(datafile), true)) 
     { 
      data = csv.ToList<string[]>(); 
     } 
    } 

    public List<string> Operate() 
    { 
    ... 
    } 

} 

मेरा प्रश्न है: मैं निपटाने को लागू करना चाहिए? और की तरह कुछ कार्य करें:

List<string> results = new List<results>(); 

using (MyClass m = new MyClass("fileM.txt")) 
      { 
       results.AddRange(m.Operate()); 
      } 

using (MyClass d = new MyClass("fileD.txt")) 
      { 
       results.AddRange(d.Operate()); 
      } 

... 

मैंने पढ़ा है कि लागू करने डिस्पोजेबल जब आप unmmanaged संसाधनों (सॉकेट, धाराओं, ...) का उपयोग की सिफारिश की है, लेकिन मेरी कक्षा में मैं केवल बड़े डेटा सरणियों की है।

एक और तरीका है प्रत्येक वस्तुओं के लिए काम करता है बनाने के लिए होगा (मुझे लगता है जी सी स्वचालित रूप से एक समारोह में बनाए गए एक वस्तु को नष्ट करेगा):

List<string> results = new List<results>(); 
results.AddRange(myFunction("fileM.txt")); 
results.AddRange(myFunction("fileD.txt")); 


public List<string> myFunction(string file) 
{ 
MyClass c = new MyClass(file); 
return results.AddRange(c.Operate()); 
} 
+0

मैंने आपका शीर्षक संपादित किया है। कृपया देखें, "[प्रश्नों में उनके शीर्षक में" टैग "शामिल होना चाहिए?] (Http://meta.stackexchange.com/questions/19190/)", जहां आम सहमति है "नहीं, उन्हें नहीं करना चाहिए"। –

उत्तर

5

IDisposable आदि तुम यहाँ मदद नहीं करेगा, क्योंकि यह कारण नहीं है इकट्ठा करने के लिए कुछ भी। इस प्रकार के परिदृश्य में, शायद सबसे अच्छा तरीका आवंटन को कम करने के लिए पूल का उपयोग करना है - अनिवार्य रूप से अपना स्वयं का मेमोरी मैनेजर बनना। उदाहरण के लिए, यदि आपका List<string> बड़ा है, तो आप सूचियों का पुनः उपयोग करके कई सरणी से बच सकते हैं - स्पष्ट रूप से उन्हें साफ़ करने के बाद। यदि आप .Clear() पर कॉल करते हैं, तो बैकिंग सरणी रीसेट नहीं होती है - यह केवल इसे खाली मानने के लिए लॉजिकल मार्कर सेट करता है। आपके विशिष्ट मामले में, आपकी कई वस्तुएं व्यक्तिगत string एस होने जा रही हैं; यह ट्रिकियर है, लेकिन कम से कम वे छोटे हैं और पीढ़ी-शून्य में एकत्रित होना चाहिए।

+1

यदि आप बैकिंग सरणी का आकार बदलना चाहते हैं तो आप 'साफ़ करें() 'कॉल करने के बाद' क्षमता = कुछ वैल्यू 'सेट कर सकते हैं। (ध्यान दें कि यह आपको वर्तमान आकार के नीचे 'क्षमता' को कम करने की अनुमति नहीं देगा, इसलिए आपको इसे पहले साफ़ करना होगा।) – porges

+0

सूची का पुन: उपयोग करना एक अच्छा विचार है, हालांकि मेरे मामले में जटिल है। मैंने कुछ सीएसवी फाइलों से डेटा पढ़ा। प्रत्येक सीएसवी के लिए, मैं डेटा के कॉलम (प्रत्येक कॉलम के लिए स्ट्रिंग की एक सूची) निकालता हूं और कुछ ग्राफ बना देता हूं। प्रत्येक सीएसवी के लिए पढ़ने वाले डेटा के लिए एक सूची का पुन: उपयोग करना आसान है। लेकिन प्रत्येक सीएसवी के कॉलम के लिए सूचियों को फिर से शुरू करना अधिक जटिल है। एक सीएसवी में 3 कॉलम (3 सूचियां) हो सकती हैं, 8 कॉलम (8 सूचियां), तो मुझे सीएसवी के अधिकतम कॉलम की अधिकतम संख्या के रूप में कई सूचियां बनाना पड़ता था। और फिर प्रत्येक कॉलम के लिए प्रत्येक सूची को दोबारा दें .. एक जटिल कोड। प्रत्येक ऑब्जेक्ट को अपने कॉलम के साथ हटाना आसान होगा :) – Alberto

3

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

आप List<T> का भी उपयोग कर सकते हैं, यह आंतरिक रूप से वही करेगा (एक सरणी आवंटित करें, इसे तब तक रखें जब तक कि यह बहुत छोटा न हो जाए, एक नया आवंटित न हो)। अगली वस्तु बनाने से पहले बस Clear

ध्यान दें कि आप एक वस्तु को इकट्ठा करने के कचरा कलेक्टर लिए मजबूर नहीं कर सकते हैं। IDisposable वास्तव में केवल अप्रबंधित संसाधनों को साफ करने के लिए उपयोग किया जाता है, क्योंकि कचरा कलेक्टर उनके बारे में नहीं जानता है, या बंद (फ़ाइल) हैंडल को बंद करने के लिए। Dispose पर कॉल करने से ऑब्जेक्ट को स्मृति से हटा दिया गया है (या इंगित नहीं करता)।

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

) आप GC.Collect() पर कॉल करके अपना डेटा एकत्र करने के लिए कचरा कलेक्टर को मजबूर कर सकते हैं।हालांकि, यह अनुशंसित नहीं है। कचरा कलेक्टर इसे अपने आप से बाहर निकालने दें।

0

यदि आप .NET 4.0 या अधिक का उपयोग कर रहे हैं, तो BlockingCollection कक्षा पर एक नज़र डालें। constructor that takes the Int32 parameter आपको संग्रह के आकार पर ऊपरी बाउंड निर्दिष्ट करने की अनुमति देता है। Add और Take विधियां थ्रॉटल के रूप में काम करती हैं। जोड़ केवल तभी सफल होगा यदि ऊपरी सीमा तक नहीं पहुंच पाई है। यदि यह है, तो यह ब्लॉक करेगा। यदि कोई आइटम मौजूद है तो ले लेंगे केवल तभी सफल होगा। यदि कोई आइटम मौजूद नहीं है, तो यह तब तक अवरुद्ध होगा जब तक कोई उपलब्ध न हो। बेशक, कक्षा में इन तरीकों के कुछ बदलाव हैं, इसलिए यह देखने के लिए कि कौन सा, यदि कोई है, तो पूरी तरह से दस्तावेज़ीकरण की जांच करें।