2012-10-02 12 views
5

के साथ मेमोरी लीक (?) मेरे पास 500MB++ आकार में से कुछ बहुत बड़ी फ़ाइलें हैं, जिसमें पूर्णांक मान हैं (वास्तव में यह थोड़ा अधिक जटिल है), मैं उन फ़ाइलों को एक लूप में पढ़ रहा हूं और अधिकतम मान की गणना कर रहा हूं सारे दस्तावेज। किसी कारण से प्रसंस्करण के दौरान स्मृति लगातार बढ़ रही है, ऐसा लगता है कि जीसी कभी भी स्मृति को रिलीज़ नहीं करता है, जो lines के पिछले उदाहरणों द्वारा अधिग्रहित किया गया है।StreamReader

मैं डेटा स्ट्रीम नहीं कर सकता और प्रत्येक फ़ाइल के लिए GetFileLines का उपयोग करना होगा। lines को एक फ़ाइल के लिए lines स्टोर करने के लिए आवश्यक स्मृति की वास्तविक मात्रा प्रदान की गई है, मुझे 5GBRAM क्यों 10 फ़ाइलों को संसाधित करने के बाद उपयोग किया जाता है? आखिरकार यह 15 फाइलों के बाद मेमोरी अपवाद के साथ दुर्घटनाग्रस्त हो गया।

गणना:

int max = int.MinValue; 

    for (int i = 0; i < 10; i++) 
    { 
     IEnumerable<string> lines = Db.GetFileLines(i); 

     max = Math.Max(max, lines.Max(t=>int.Parse(t))); 
    } 

GetFileLines कोड:

public static List<string> GetFileLines(int i) 
    { 
     string path = GetPath(i); 

     // 
     List<string> lines = new List<string>(); 
     string line; 

     using (StreamReader reader = File.OpenText(path)) 
     { 
     while ((line = reader.ReadLine()) != null) 
     { 
      lines.Add(line); 
     } 

     reader.Close(); 
     reader.Dispose(); // should I bother? 
     } 

     return lines; 
    } 
+0

क्या आप 'लाइनों को कॉल करते हैं। क्लीयर()' विधि? – opewix

+0

मुझे नहीं करना चाहिए? – user1514042

+0

10 x 500 एमबी = 5 जीबी। आप सभी फाइलों की सूची सूची में रखते हैं * सूची लाइन *। ReadAllLines के रूप में वही perf() – Cybermaxs

उत्तर

5

बहुत बड़ी फ़ाइल के लिए, विधि ReadLines सर्वाधिक उपयुक्त होगा, क्योंकि यह आस्थगित निष्पादन, यह स्मृति और सरल में सभी लाइनों लोड नहीं करता है उपयोग करने के लिए:

Math.Max(max, File.ReadLines(path).Max(line => int.Parse(line))); 

अधिक जानकारी:

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

संपादित करें:

यह कैसे ReadLines दृश्य के पीछे लागू है:

public static IEnumerable<string> ReadLines(string fileName) 
    { 
     string line; 
     using (var reader = File.OpenText(fileName)) 
     { 
      while ((line = reader.ReadLine()) != null) 
       yield return line; 
     } 
    } 

इसके अलावा, यह समानांतर प्रसंस्करण का उपयोग कर प्रदर्शन आप एक से अधिक फ़ाइलों

+0

क्षमा करें प्रसंस्करण तर्क अधिक जटिल है नमूना केवल इस तथ्य को दर्शाता है कि यह पूरी तरह से पढ़ने की प्रक्रिया से decoupled है। – user1514042

+0

@ user1514042: इससे कोई फर्क नहीं पड़ता, आप इसे LINQ के साथ बहुत बड़ी फ़ाइल –

+0

संसाधित करने के लिए उपयोग कर सकते हैं जब यह लाइनों की वास्तविक संख्या 500K ++ है तो प्रदर्शन को मार नहीं पाएगा? – user1514042

4

क्योंकि आप स्मृति में पार्स परिणाम के लिए संदर्भ रख रहे हैं जाने के बाद उन्हें संसाधन पूर्ण कर रहे हैं आप दुर्घटनाग्रस्त जा सकता है (कोड आप नहीं करता है दिखाने ऐसा मत करो, लेकिन क्या वह वही कोड है जिसे आप चलाते हैं?)। यह बेहद असंभव है कि StreamReader में ऐसी बग है।

क्या आप वाकई स्मृति में सभी फाइलों को एक साथ पढ़ना चाहते हैं? List<string> को ऊपर लोड करने के बजाय IEnumerable<string> के रूप में लाइनों के एक समेकित अनुक्रम का उपयोग करना संभव हो सकता है। इस कोड में कम से कम कुछ भी नहीं है जो इसे प्रतिबंधित करता है।

अंत में, Close और Dispose कॉल अनावश्यक हैं; using स्वचालित रूप से इसका ख्याल रखता है।

+0

वैसे मैं केवल मूल्य प्रकारों का उपयोग करता हूं, क्या वे अभी भी संदर्भ धारण कर सकते हैं? – user1514042

+0

बेशक वे कर सकते हैं। यदि आप किसी भी तरह से सूची तक पहुंच सकते हैं, तो कोई इसका संदर्भ ले रहा है। – Jon

+0

सच है, लेकिन यह हर जगह बदल जाता है, तो आपका बिंदु सही होगा अगर मैं नाखुश अंतिम 500 एमबी साफ़ नहीं किया गया था, लेकिन मुझे एक अलग समस्या है। – user1514042

0

आप memmory (सूची लाइनों) में पूरी फ़ाइल

मुझे लगता है कि तुम सिर्फ एक समय में एक लाइन पढ़ सकते हैं और सबसे अधिक संख्या में रख सकता है पढ़ रहे हैं?

यह आपको बहुत सारे राम बचाएगा।

+0

प्रत्येक पंक्ति को प्रक्रिया के लिए 5 सेकंड लगते हैं, यही कारण है कि उन्हें पढ़ने और फिर प्रक्रिया को पढ़ने में बड़ा समय लगता है। हम बहुत कुछ कर रहे हैं, जो प्रदर्शन परीक्षणों द्वारा पुष्टि की जाती है। – user1514042

1

कि क्यों लागू नहीं निम्नलिखित के रूप में:

int max = Int32.MinValue; 
using(var reader = File.OpenText(path)) 
{ 
    while ((line = reader.ReadLine()) != null) 
    { 
     int current; 
     if (Int32.TryParse(line, out current)) 
      max = Math.Max(max, current); 
    }  
} 
0

ऐसा प्रतीत होता है जब सुधार करने के लिए सिफारिश की है कि आप हमेशा स्मृति में पूरी फाइल लोड कर रहे हैं।साथ ही, आप फ़ाइल की प्रत्येक पंक्ति के लिए प्रबंधित ऑब्जेक्ट्स (सूची) भी बना रहे हैं।

कोई कारण नहीं है कि आपकी मेमोरी उपयोग बढ़ेगी।

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

0

ठीक है, अगर आप एक समाधान चाहते हैं जहां आप एक ही समय में पूरी फ़ाइल पढ़ सकते हैं, क्योंकि आप सुनिश्चित हैं कि आपको उस प्रदर्शन लाभ की आवश्यकता है, तो चलिए इसे इस तरह करते हैं ताकि आपके पास ऐसा न हो एक स्मृति मुद्दा।

public static int GetMaxForFile(int i) 
{ 
    string path = GetPath(i); 

    var lines = new List<string>(File.ReadAllLines(path)); 

    // you MUST perform all of your processing here ... you have to let go 
    // of the List<string> variable ... 
    int max = Math.Max(max, lines.Max(t=>int.Parse(t))); 

    // this may be redundant, but it will cause GC to clean up immediately 
    lines.Clear(); 
    lines = null; 

    return max; 
} 
संबंधित मुद्दे