14

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.

+1

Sei sicuro che non è in attesa sui collegamenti per la piscina? Hai provato a ingrandire la dimensione del pool di connessione? – Maess

+0

@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. –

+0

@Maess: Perfmon mostra solo 11 connessioni logiche e 11 connessioni utente all'istanza SQL, molto al di sotto del limite del pool di connessioni. –

risposta

5

Quanto segue riepiloga la mia interazione con il team Entity Framework su questo problema.Aggiornerò la risposta se saranno disponibili ulteriori informazioni

  • Il problema può essere riprodotto in Microsoft.
  • Il conflitto di handle è correlato a I/O di rete (anche con SQL Server su localhost). In particolare, esiste un conflitto per il buffer di lettura per I/O di rete in System.Data.dll.
  • Il team EF sta ora collaborando con il team di SQL Connectivity per comprendere meglio il problema.
  • Non ci sono ancora indicazioni da Microsoft su come minimizzare l'impatto di questa contesa.

UPDATE

Questo problema viene ora monitorata su CodePlex:

http://entityframework.codeplex.com/workitem/636?PendingVoteId=636

+0

Grazie mille Eric. Sono abbastanza interessato a questo coz ho uno scenario simile. Abbiamo un problema per questo su connect.microsoft.com in modo che possiamo tracciare i suoi progressi? – Dodd

+0

@Dodd: È stato rintracciato su Codeplex da quando EF ora è open source (ma ha ancora funzionato dal team di Microsoft). Aggiunto il link. –