9

Me pregunto si alguno de ustedes sabe por qué mi rendimiento es terrible;Paralelo con Entity Framework. El rendimiento es espectacular en comparación con el lanzamiento de varios ejecutables, ¿por qué?

Lo que estoy tratando de lograr; Genera 2,2 millones de archivos. Para crear cada archivo, se necesitan de 2 a 5 llamadas a la base de datos en promedio.

El servidor en el que estoy trabajando tiene 24 núcleos y 190 GB de RAM.

Dividí los archivos que necesito generar en 24 lotes.

Whey Utilizo el siguiente código, obtengo un mal rendimiento. El proceso de generación lleva más de una hora.

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

Sin embargo, cuando me aseguro de que mi programa recibe un parámetro de lo que el progama sabe qué lote para generar así que no es necesario utilizar la funcionalidad paralelo. Si ejecuto el programa para cada lote con el siguiente archivo .bat;

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

¡Corre increíblemente rápido! ¡El proceso de generación total demora menos de 15 minutos! Este archivo por lotes también se asegura de que cada núcleo tenga un uso de CPU de alrededor del 90%. Cuando uso el enfoque Paralelo, solo obtengo un 30-40% de uso.

¿Alguien tiene una explicación lógica para esto? Estaba contento con este proyecto porque finalmente tuve la posibilidad de usar la biblioteca .NET 4 Parallel en combinación con EF pero desafortunadamente, me decepcionó un poco :-)

Personalmente tengo una ligera sospecha de que EF es el cuello de botella aquí ... ¿Guarda en caché algunas cosas internamente que impone algunos bloqueos cuando varios procesos están obteniendo datos?

me ilumine :-)

+0

¿Qué versión de EF estás usando? –

+0

¿Hay límites impuestos por el adaptador de base de datos en el número de conexiones por programa? Algunos adaptadores tienen ese tipo de problema, al igual que HttpWebRequest. – em70

+0

@ emaster70 - podría estar en algo allí, http://stackoverflow.com/questions/3526617/are-ado-net-2-0-connection-pools-pre-application-domain-or-per-process –

Respuesta

4

No puedo hablar de por qué el otro archivo EXE funciona bien, pero puedo ofrecer una sugerencia para el código que presente.

Mencionaste que dividiste tu trabajo en 24 lotes, luego usaste ForEach sobre la lista de lotes. Con esta configuración, parecería que cada uno de nuestros 24 núcleos puede estar trabajando en 1 archivo a la vez. Creo que ese es tu cuello de botella.

Cada núcleo podría estar haciendo mucho más si lo permite. Pruebe algo como esto:

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

O simplemente podría deshacerse de los lotes por completo y darle la lista completa de archivos. La biblioteca paralela de tareas se ocupará de usar núcleos múltiples para usted.

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

Es probable que ya lo saben, pero tenga en cuenta que el context is not thread safe, así que hay que crear uno nuevo dentro de la estructura interna más Parallel.ForEach.

Cuestiones relacionadas