2012-05-09 21 views
9

Ho una classe, diciamo "MyComputation" che esegue molti calcoli in un costruttore lungo. Richiede tipicamente circa 20 ms per essere eseguito quando eseguito da solo (senza I/O del disco o operazioni di rete). 100 o giù di lì istanze di questa classe sono creati da una classe genitore, dire "ComputeParent", che li mette in coda in un ThreadPool come elementi di lavoro:Prestazioni dell'applicazione Thread # C# degradante nel tempo

ThreadPool.QueueUserWorkItem(myComputationCall, my_computation_data); 

"myComputationCall" si presenta così:

public static void myComputationCall(Object my_computation_data) 
    { 
     try 
     { 
      MyDataObject data = (MyDataObject)my_computation_data; 

      var computation_run = new MyComputation(data.parameter1, data.parameter2); 

      data.result = computation_run.result; 
     } 
     finally 
     { 
      if (Interlocked.Decrement(ref num_work_items_remaining) == 0) 
       done_event.Set(); 
     } 
    } 

done_event è un ManualResetEvent statico:

private static ManualResetEvent done_event; 

    ... 

    done_event = new ManualResetEvent(false); 

corro ComputeParent circa 500 volte o più, per i vari parametri di input. Quindi ho un sacco di classi annidate. Il problema è che il tempo necessario per eseguire ComputeParent aumenta gradualmente. Ci sarà una certa quantità di variazione tra quanto tempo ci vuole per eseguire ogni particolare ComputeParent, ma la quantità di tempo aumenta abbastanza costantemente (geometricamente, ogni iterazione successiva richiede più tempo di una quantità maggiore).

Il consumo di memoria del programma non aumenta sensibilmente nel tempo sebbene sia piuttosto alto (~ 300 MB). È in esecuzione su un computer con 8 core logici e l'utilizzo del processore sembra essere molto esplosivo. Non sono sicuro di cos'altro potrebbe essere rilevante per il problema.

Preferirei non dover eseguire ComputeParent tramite i file batch, anche se il problema non sembra sorgere quando questo è fatto.

+2

C'è qualche motivo (come .NET <4) di non usare il TPL? –

+6

Dovresti iniziare a profilare. Misurare è sapere. Potrebbe essere aumentata l'attività di GC, altri thread, ... Non vi è alcun indizio evidente in questo codice. –

+2

Hai provato a profilarlo? Raccomando anche l'uso della TPL. – Simon

risposta

3

Se il numero di thread disponibili nel ThreadPool diventa 0 e si continuano ad aggiungere nuovi elementi di lavoro, gli elementi di lavoro appena aggiunti "si attendono". Ciò significa che il tuo ComputeParent attenderà le sue istanze di "myComputationCall". Avviare sempre più ComputeParent causerà un aumento del tempo di esecuzione medio di essi.

0

Alla domanda è stata data risposta. Grazie a tutti i poster.

Per gli altri con un problema simile, suggerirei la Libreria parallela attività come suggerito da Henk.

Problemi correlati