2010-08-04 38 views
5

@GilShalit तैनात टी his comment a year ago:GetOracleDecimal स्मृति रिसाव

"ठीक है, हम एक स्मृति रिसाव से लड़ने में (कोड हम एक ग्राहक को आपूर्ति में) के बाद ODP (नेट 2.0) अविश्वास के लिए आए हैं से अधिक वर्ष के लिए GetOracleDecimal ... शुभकामनाएँ! " - गिलशलिट अगस्त 27 '0 9 12:44

आपने इसे कैसे हल किया?

हमारे पास ऐसी सेवा है जो हर कुछ मिनटों में ओरेकल डेटाबेस से पूछताछ करता है जो स्मृति जारी नहीं कर रहा है; WinDbg का उपयोग करके कुछ जांच के बाद मैंने पाया कि यह प्रकार अंतिम कतार में पिलिंग हो रहा है: Oracle.DataAccess.Types.OpoDecCtx।

decimal volume = (decimal)OracleDecimal.SetPrecision(reader.GetOracleDecimal(5), 28); 

मैं इस पर टिप्पणी की और स्मृति रिसाव गायब हो गया:

यहाँ लाइन मुझे लगता है कि समस्या है।

किसी भी विचार की सराहना की जाएगी - धन्यवाद!

+0

आपका प्रश्न क्या है? –

+0

GetOracleDecimal क्यों लीक मेमोरी है और समस्या को हल करने के लिए पोस्ट किए गए कथन को मैं कैसे संशोधित कर सकता हूं? मैं उम्मीद कर रहा था कि गिलशलिट यहां छिपे रहेंगे और टिप्पणी दे सकते हैं लेकिन मुझे इसमें किसी भी व्यक्ति से सुनकर खुशी हो रही है। धन्यवाद – Tim

+0

हर दिन हजारों प्रश्न पोस्ट किए जाते हैं, और ऐसा लगता है कि गिल एक बहुत ही लगातार आगंतुक है। यदि आप उसका ध्यान आकर्षित करना चाहते हैं तो आपको @ प्रतीक का उपयोग करने की आवश्यकता है, जो उसके प्रतिसाद टैब में दिखाई देगा। इस तरह @GilShalit – APC

उत्तर

8

यह ओडीपी.NET के साथ एक पुराना मुद्दा है (यहां देखें: Memory Problems with ODP.NET 10.1.0.4)।

OracleDecimal प्रकार OpoDecCtx नामक एक आंतरिक वर्ग के उदाहरण का संदर्भ रखता है। OpoDecCtx IDisposable लागू करता है (क्योंकि यह स्वयं अप्रबंधित स्मृति का संदर्भ देता है), लेकिन चूंकि ओरेकलडिसीमल आईडीस्पोजेबल को लागू नहीं करता है, इसलिए आपको अंतर्निहित अप्रबंधित स्मृति को मुक्त करने के लिए कचरा कलेक्टर को चलाने के लिए इंतजार करना होगा। आप यह सब एक उपकरण जैसे .NET परावर्तक का उपयोग करके देख सकते हैं।

हालांकि यह तकनीकी रूप से "भौतिक" स्मृति रिसाव नहीं है (स्मृति अंततः मुक्त हो जाएगी), यह वास्तव में एक समस्या है जब आप ओरेकलडिमल प्रकार की बड़ी मात्रा में उदाहरणों से निपट रहे हैं। मैं वैसे भी क्यों Oracle बस IDisposable को लागू नहीं करता है पता नहीं है, यह करने के लिए एक सरल बात है ...

, मेरा सुझाव है कि आप कुछ हैक काम खुद कर, प्रतिबिंब का उपयोग:

public static class OracleExtentions 
{ 
    public static void Dispose(this OracleDecimal od) // build an extension method 
    { 
     if (OracleDecimalOpoDecCtx == null) 
     { 
      // cache the data 
      // get the underlying internal field info 
      OracleDecimalOpoDecCtx = typeof(OracleDecimal).GetField("m_opoDecCtx", BindingFlags.Instance | BindingFlags.NonPublic); 
     } 
     IDisposable disposable = OracleDecimalOpoDecCtx.GetValue(od) as IDisposable; 
     if (disposable != null) 
     { 
      disposable.Dispose(); 
     } 
    } 

    private static FieldInfo OracleDecimalOpoDecCtx; 
} 

और तुम होगा इस तरह इसका इस्तेमाल:

OracleDecimal od = reader.GetOracleDecimal(5); 
decimal volume = (decimal)OracleDecimal.SetPrecision(od, 28); 
od.Dispose(); 
+0

+1, ठोस जवाब! –

+0

यह बहु थ्रेडेड अनुप्रयोगों में एक गंभीर समस्या है।के रूप में: oraclesi पूरक FINALIZER थ्रेड को मार/ब्लॉक कर सकता है जिसका मतलब है कि अंतिमकरण की आवश्यकता नहीं है, अब और भी साफ हो जाता है। – TomTom

+0

उपर्युक्त समाधान वास्तव में अच्छी तरह से काम करता है, लेकिन सावधान रहें क्योंकि इसका काफी महत्वपूर्ण प्रदर्शन प्रभाव है। – tjdecke

0

मैं अगर यह संभव है ODP.NET से अन्य प्रदाता बदलने के लिए, लेकिन हम ODP खुदाई एक लंबे समय पहले से इस हल पता नहीं है ... और एक 3rd- उपयोग कर रहे हैं पार्टी (वाणिज्यिक) ADO.NET प्रदाता (संबद्ध नहीं) ... इस लिंक को देखें http://www.devart.com/dotconnect/oracle/docs/

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