SfondoEntity Framework e parallelismo
Ho un'applicazione che riceve i dati periodica dump (file XML) e li importa in un database esistente utilizzando Entity Framework 5 (primo codice). L'importazione avviene tramite EF5 piuttosto che BULK INSERT o BCP perché devono essere applicate le regole aziendali già esistenti nelle entità.
L'elaborazione sembra essere legata alla CPU nell'applicazione stessa (il sottosistema di I/O del disco estremamente veloce abilitato alla cache di scrittura mostra quasi zero tempi di attesa del disco durante il processo e SQL Server non mostra più dell'8% -10% del tempo CPU).
Per migliorare l'efficienza, ho costruito una pipeline using TPL Dataflow con componenti:
Read & Parse XML file
|
V
Create entities from XML Node
|
V
Batch entities (BatchBlock, currently n=200)
|
V
Create new DbContext/insert batched entities/ctx.SaveChanges()
vedo un notevole aumento delle prestazioni in questo modo, ma non è possibile ottenere la CPU sopra circa il 60%.
Analisi
Sospettando una sorta di conflitto di risorse, ho eseguito il processo utilizzando dati contesa di risorse del VS2012 Profiler (concorrenza) modalità.
Il profiler mi mostra il 52% di contesa per una risorsa denominata Handle 2. Foratura in, vedo che il metodo creando la più contesa per Maniglia 2 è
System.Data.Entity.Internal.InternalContext.SaveChanges()
In secondo luogo, a circa 40% il maggior numero di contese come SaveChanges(), è
System.Data.Entity.DbSet`1.Add(!0)
Domande
- Come posso capire cosa gestire 2 è davvero (e .es. parte di TPL, parte di EF)?
- EF rallenta le chiamate per separare le istanze DbContext da thread separati? Sembra che ci sia una risorsa condivisa per cui stanno lottando.
- C'è qualcosa che posso fare per migliorare il parallelismo in questo caso?
UPDATE
Per la corsa in questione, il massimo grado di parallelismo per il compito che chiama SaveChanges è impostato a 12 (Ho provato vari valori compresi illimitata in cicli precedenti).
UPDATE 2
squadra EF di Microsoft ha fornito un feedback. Vedi la mia risposta per un riassunto.
Sei sicuro che non è in attesa sui collegamenti per la piscina? Hai provato a ingrandire la dimensione del pool di connessione? – Maess
@Maess: per la corsa in questione, ho impostato il grado massimo di parallelismo su 12. Se ho capito correttamente, la dimensione massima predefinita del pool di connessioni è 100. Tuttavia, proverò a impostarla in modo esplicito più in alto. –
@Maess: Perfmon mostra solo 11 connessioni logiche e 11 connessioni utente all'istanza SQL, molto al di sotto del limite del pool di connessioni. –