2014-09-05 16 views
6

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

class Program 
{ 
    static void test() 
    { 
    } 

    static void Main(string[] args) 
    { 
     while (true) 
     {    
      Thread test_thread = new Thread(() => test()); 
      test_thread.Start(); 
      Thread.Sleep(20); 
     } 
    } 
} 

इस प्रोग्राम को चलाने से, मुझे लगता है कि प्रोग्राम का मेमोरी उपयोग बिना रोक के लगातार बढ़ता है। कुछ ही मिनटों में स्मृति उपयोग 100 एमबी से अधिक अच्छी तरह से चला जाता है और चढ़ाई करता रहता है। अगर मैं लाइन test_thread.Start(); पर टिप्पणी करता हूं, प्रोग्राम द्वारा उपयोग की गई स्मृति लगभग कुछ मेगाबाइट्स पर अधिकतम हो जाती है, और स्तर समाप्त हो जाता है। मैंने जीसी.कोलेक्ट() का उपयोग करते हुए लूप के अंत में कचरा संग्रह को मजबूर करने का भी प्रयास किया, लेकिन ऐसा कुछ नहीं लगता था।

मैंने सोचा कि जैसे ही फ़ंक्शन समाप्त हो गया है, जैसे ही जीसी इसे अपनाने की अनुमति दे रहा है, लेकिन ऐसा प्रतीत नहीं होता है। मुझे यहां कुछ गहराई से समझना नहीं चाहिए, और मैं इस रिसाव को ठीक करने में कुछ मदद की सराहना करता हूं। अग्रिम में धन्यवाद!

उत्तर

9

यह डिज़ाइन द्वारा है, आपका परीक्षण प्रोग्राम रनवे मेमोरी उपयोग प्रदर्शित करना चाहता है। आप Taskmgr.exe से अंतर्निहित कारण देख सकते हैं। देखें + कॉलम का चयन करें और "हैंडल" पर टिकटें। देखें कि आपकी प्रक्रिया के लिए हैंडल की संख्या लगातार बढ़ रही है। मेमोरी उपयोग उस के साथ बढ़ता है, जो हैंडल ऑब्जेक्ट्स द्वारा उपयोग की गई अप्रबंधित स्मृति को दर्शाता है।

डिजाइन पसंद एक बहुत ही साहसी था, सीएलआर प्रति थ्रेड 5 ऑपरेटिंग सिस्टम ऑब्जेक्ट्स का उपयोग करता है। नलसाजी, सिंक्रनाइज़ेशन के लिए इस्तेमाल किया। ये वस्तुएं स्वयं डिस्पोजेबल हैं, डिजाइन पसंद थी थ्रेड क्लास IDISposable लागू करने के लिए। यह .NET प्रोग्रामर पर काफी कठिनाई होगी, सही समय पर निपटान() कॉल करना बहुत मुश्किल है। साहस जो टास्क क्लास डिज़ाइन बीटीडब्ल्यू में प्रदर्शित नहीं हुआ था, जिसके कारण बहुत सारे हाथ-झुकाव और general advice not to bother थे।

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

यह हो सकता है, हम आपका असली कार्यक्रम नहीं देख सकते हैं। ऐसे सिंथेटिक परीक्षण से बहुत से निष्कर्ष निकालने से सावधान रहें। आप Perfmon.exe के साथ जीसी आंकड़े देख सकते हैं, यह आपको एक विचार देता है अगर यह अक्सर पर्याप्त चल रहा है। एक सभ्य .NET स्मृति प्रोफाइलर पसंद का हथियार है। जीसी। कोलेक्ट() बैकअप हथियार है। उदाहरण के लिए:

static void Main(string[] args) { 
    int cnt = 0; 
    while (true) { 
     Thread test_thread = new Thread(() => test()); 
     test_thread.Start(); 
     if (++cnt % 256 == 0) GC.Collect(); 
     Thread.Sleep(20); 
    } 
} 

और आप इसे अब और आगे उछाल देखेंगे, कभी भी 4 एमबी से अधिक नहीं हो रहा है।

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