2017-03-27 16 views
11

मेरी समझ में, प्रोग्राम चल रहा है, जबकि जेआईटी-एड कोड स्मृति से कभी भी रिलीज़ नहीं होता है। क्या इसका मतलब यह है कि अभिव्यक्ति वृक्षों पर बार-बार .Compile() को कॉल करने से स्मृति लीक हो जाती है?संकलित पेड़ रिसाव संकलित करें?

इसका निहितार्थ केवल स्थिर रचनाकारों में अभिव्यक्ति वृक्ष संकलित करना होगा या उन्हें किसी अन्य तरीके से कैश करना होगा, जो कि सरल नहीं हो सकता है। सही?

+0

क्यों आप बार-बार एक ही अभिव्यक्ति संकलन होगा? शायद कुछ कोड उदाहरण प्रदान करें? – Evk

+2

मान लीजिए कि 'कॉम्पाइल() 'अभिव्यक्ति वृक्ष पर समान है? –

+1

@Evk क्योंकि कभी-कभी आप उन्हें 'शब्दकोश <>', या स्थिर चर में कैश नहीं करते हैं ... यह एक दिलचस्प सवाल है। – xanatos

उत्तर

9

वे हैं शायद GCed ... LambdaExpression.Compile()LambdaCompiler.Compile(LambdaExpression, DebugInfoGenerator) वर्ग, का उपयोग करता है through one of the LambdaCompiler constructors का उपयोग करता DynamicMethod कि, MSDN से:

परिभाषित करता है और एक गतिशील विधि है कि, संकलित किया जा सकता मार डाला, और त्याग का प्रतिनिधित्व करता है। कचरा संग्रह के लिए छोड़े गए तरीके उपलब्ध हैं।

+0

तो संकलित अभिव्यक्ति जीसीएड नहीं हैं? यह पढ़ता है जैसे कि छोड़े गए अभिव्यक्तियां जीसी'एड हैं। –

+0

@ पैट्रिकहोफमैन यह विपरीत है ... वे ** ** जीसीएड हैं ... "डिकर्डेड" के लिए मुझे लगता है कि उनका मतलब है "अब और संदर्भित नहीं"। कहीं भी "छोड़ें()" विधि नहीं है, इसलिए विवरण का कोई भी अन्य अर्थ व्यर्थ होगा। – xanatos

4

मैं लगातार पृष्ठभूमि में एक अभिव्यक्ति के पेड़ पैदा करने और फिर सभी कचरा इकट्ठा करने और जीयूआई धागा में इस्तेमाल अंतरिक्ष की निगरानी के द्वारा इस परीक्षण की कोशिश की।

ऐसा लगता है कि कुछ घंटों के बाद स्मृति उपयोग लगभग 655000 बाइट्स पर स्थिर रहता है। तो मैं कहूंगा कि अभिव्यक्ति के पेड़ों के साथ जंगली जाना सुरक्षित है।

Expression tree memory usage

किसी को भी मेरी hacky परीक्षण कोड चाहता है, यहाँ यह है:

using System; 
using System.Collections.Generic; 
using System.Linq.Expressions; 
using System.Threading; 
using System.Windows.Forms; 

namespace Experiments 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 

      // Ensuring that always the same amount of memory is used for point storage. 
      bytesUsed = new Queue<long>(1000); 
      var points = chart1.Series[0].Points; 
      for (var i = 0; i < 1000; ++i) 
      { 
       bytesUsed.Enqueue(0); 
       points.Add(0); 
      } 


      thread = new Thread(ThreadMethod); 
      thread.Start(); 
      timer1.Interval = 10000; 
      timer1.Enabled = true; 
      timer1_Tick(null, null); 
     } 

     private readonly Queue<long> bytesUsed; 
     private void timer1_Tick(object sender, EventArgs e) 
     { 
      GC.Collect(); 
      GC.WaitForPendingFinalizers(); 
      GC.Collect(); 

      bytesUsed.Dequeue(); 
      bytesUsed.Enqueue(GC.GetTotalMemory(false)); 

      var points = chart1.Series[0].Points; 
      points.Clear(); 
      foreach (var value in bytesUsed) 
       points.Add(value); 
     } 

     private Thread thread; 
     private volatile bool stopping; 
     private void ThreadMethod() 
     { 
      var random = new Random(); 

      while (!stopping) 
      { 
       var constant = Expression.Constant(random.Next(), typeof(int)); 
       var param = Expression.Parameter(typeof(int)); 

       var mul = Expression.Multiply(param, constant); 
       var add = Expression.Multiply(mul, param); 
       var sub = Expression.Subtract(add, constant); 

       var lambda = Expression.Lambda<Func<int, int>>(sub, param); 
       var compiled = lambda.Compile(); 
      } 
     } 

     protected override void Dispose(bool disposing) 
     { 
      stopping = true; 
      if (thread != null && disposing) 
       thread.Join(); 

      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 
    } 
} 
संबंधित मुद्दे