2010-02-25 12 views
14

Abbiamo un componente del server scritto in .Net 3.5. Funziona come servizio su Windows Server 2008 Standard Edition. Funziona alla grande ma dopo un po 'di tempo (giorni) notiamo massicci rallentamenti e un set di lavoro aumentato. Ci aspettavamo un qualche tipo di perdita di memoria e abbiamo utilizzato WinDBG/SOS per analizzare i dump del processo. Sfortunatamente GC Heap non mostra alcuna perdita, ma abbiamo notato che l'heap del codice JIT è cresciuto da 8 MB dopo l'avvio a più di 1 GB dopo pochi giorni.Codice JIT .NET Cache che perde?

Non usiamo tecniche di generazione di codice dinamico da parte nostra. Usiamo Linq2SQL, noto per la generazione dinamica di codice, ma non sappiamo se possa causare un tale problema.

La domanda principale è se esiste una tecnica per analizzare il dump e controllare da dove provengono tutti i blocchi di Heap di codice host mostrati nei dump di WinDBG?

[Update]

Nel frattempo abbiamo fatto un po 'di analisi e aveva Linq2SQL come probabile sospetto, soprattutto perché non usiamo query precompilati. Il seguente programma di esempio crea esattamente lo stesso comportamento in cui vengono creati sempre più blocchi di heap del codice host.

using System; 
using System.Linq; 
using System.Threading; 

namespace LinqStressTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      for (int i = 0; i < 100; ++ i) 
       ThreadPool.QueueUserWorkItem(Worker); 
      while(runs < 1000000)    
      { 
       Thread.Sleep(5000); 
      } 
     } 

     static void Worker(object state) 
     { 
      for (int i = 0; i < 50; ++i) 
      { 
       using (var ctx = new DataClasses1DataContext()) 
       { 
        long id = rnd.Next(); 
        var x = ctx.AccountNucleusInfos.Where(an => an.Account.SimPlayers.First().Id == id).SingleOrDefault(); 
       } 
      } 
      var localruns = Interlocked.Add(ref runs, 1); 
      System.Console.WriteLine("Action: " + localruns); 
      ThreadPool.QueueUserWorkItem(Worker); 
     } 

     static Random rnd = new Random(); 
     static long runs = 0; 
    } 
} 

Quando sostituiamo la query di Linq con una precompilata, il problema sembra scomparire.

+0

@pitchfork - un po 'di un pensiero casuale. Hai provato a disattivare il rilevamento delle modifiche in 'DataContext'? 'ctx.ObjectTrackingEnabled = false' come prima riga all'interno dell'istruzione using? –

risposta

0

L'unico modo che conosco di perdita di memoria in .net è dovuta alla gestione di eventi, check this out:

  1. link1
  2. Inoltre, date un'occhiata alla seguente domanda: How do I avoid a memory leak with LINQ-To-SQL?
  3. anche , dai un'occhiata al profiler ANTS
  4. E, hai considerato, che forse, ad un certo punto avrai molti thread in esecuzione? che consumerà in modo nativo molta memoria?
+0

Grazie per i suggerimenti. Usando WinDBG siamo stati in grado di dimostrare che non perdiamo memoria nell'heap gestito, inoltre eliminiamo sempre il nostro DataContext dopo che l'unità di lavoro è stata completata. – user173674

1

Utilizzare un 'singleton' DataContext, invece di ricrearlo tutto il tempo nel ciclo.

Sono sicuro che l'effetto sarà lo stesso delle query compilate.

Aggiornamento:

Questo problema è destinato a essere 'rettificato' in .NET 4 in quanto supporta assemblaggi dinamici GC'able.