9

Mi chiedo se qualcuno di voi sa perché la mia esibizione è terribile;Parallelo con Entity Framework. Le prestazioni sono drammatiche rispetto al lancio di più eseguibili, perché?

Quello che sto cercando di ottenere; Genera 2,2 milioni di file. Per creare ciascun file, in media sono necessari 2-5 databasecall.

Il server su cui sto lavorando ha 24 core e 190 GB di RAM.

Ho diviso i file che ho bisogno di generare in 24 lotti.

Whey Uso il seguente codice, ottengo prestazioni scadenti. Il processo di generazione richiede più di un'ora.

Parrallel.ForEach(batches, batch => 
{ 
    using (var ctx = new MyContext()) 
    { 
     for each(var file in batch.Files) 
     { 
      GenerateFile(file); 
     } 
    } 
}); 

Tuttavia, quando mi assicuro che il mio programma riceve un parametro in modo che il progamma sa quali batch per generare quindi non ho bisogno di utilizzare la funzionalità in parallelo. Se eseguo il programma per ogni batch con il seguente file .bat;

START CaMaakEiBericht.exe \B1 
START CaMaakEiBericht.exe \B2 
... 
START CaMaakEiBericht.exe \B24 

Funziona incredibilmente veloce! Il processo di generazione totale richiede meno di 15 minuti! Questo file batch si assicura anche che ogni core abbia un utilizzo della CPU attorno al 90%. Quando utilizzo l'approccio Parallel, ottengo solo il 30-40% di utilizzo.

Qualcuno ha una spiegazione logica per questo? Sono stato soddisfatto di questo progetto perché ho finalmente avuto la possibilità di utilizzare la libreria .NET 4 Parallel in combinazione con EF, ma sfortunatamente mi ha un po 'deluso :-)

Personalmente ho una leggera sospetta che EF sia il collo di bottiglia qui ... Memorizza internamente alcune cose che impongono dei blocchi quando più processi prelevano i dati?

mi illumini :-)

+0

Quale versione di EF stai usando? –

+0

Ci sono dei limiti imposti dall'adattatore db sul numero di connessioni per programma? Alcuni adattatori hanno questo tipo di problema, proprio come HttpWebRequest. – em70

+0

@ emaster70: potresti trovarti lì, http://stackoverflow.com/questions/3526617/are-ado-net-2-0-connection-pools-pre-application-domain-or-per-process –

risposta

4

non posso parlare per spiegare perché il vostro altro file EXE funziona bene, ma posso offrire un suggerimento per il codice che si presenti.

Hai accennato al fatto che hai diviso il tuo lavoro in 24 lotti, quindi hai utilizzato ForEach nell'elenco dei batch. Con questa configurazione, sembrerebbe che ognuno dei nostri 24 core possa lavorare su 1 file alla volta. La mia ipotesi è che è il collo di bottiglia.

Ogni core potrebbe fare molto di più se lo si lascia. Provare qualcosa di simile:

Parallel.ForEach(batches, batch => 
{ 
    Parallel.ForEach(batch.Files, file => 
    { 
     using (var ctx = new MyContext()) 
     { 
      GenerateFile(file); 
     }  
    } 
});

Oppure si può semplicemente sbarazzarsi dei lotti del tutto e dargli la lista completa dei file. La libreria parallela delle attività si occuperà di utilizzare più core per te.

Parallel.ForEach(Files, file => 
{ 
    using (var ctx = new MyContext()) 
    { 
     GenerateFile(file); 
    }  
});

Probabilmente già lo sanno, ma di tenere presente che il context is not thread safe, quindi bisogna crearne uno nuovo all'interno della struttura più interno Parallel.ForEach.

Problemi correlati