ContexteEntity Framework et Parallélisme
J'ai une application qui reçoit des décharges données périodiques (fichiers XML) et de les importer dans une base de données existante en utilisant Entity Framework 5 (premier code). L'importation s'effectue via EF5 plutôt que BULK INSERT ou BCP, car les règles métier qui existent déjà dans les entités doivent être appliquées. Le traitement semble être lié à la CPU dans l'application elle-même (le sous-système d'E/S du disque extrêmement rapide et en cache d'écriture affiche un temps d'attente de disque quasi nul pendant tout le processus et SQL Server ne dépasse pas 8% à 10% du temps CPU).
Pour améliorer l'efficacité, je construit un pipeline using TPL Dataflow avec des composants à:
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()
Je vois une augmentation substantielle de la performance en faisant cela, mais ne peut pas obtenir la CPU supérieure à environ 60%.
Analyse
Soupçonnant une sorte de contention des ressources, je courais le processus en utilisant les données de contention des ressources de VS2012 Profiler () d'accès concurrentiel en mode.
Le profileur affiche 52% de contention pour une ressource intitulée Poignée 2. Le forage dans, je vois que la méthode créant la plus compétition pour poignée 2 est
System.Data.Entity.Internal.InternalContext.SaveChanges()
deuxième place, à environ 40% autant de thèses que SaveChanges(), est
System.Data.Entity.DbSet`1.Add(!0)
Questions
- Comment puis-je savoir ce que poignée 2 est vraiment (e .g. partie de TPL, partie de EF)?
- Est-ce que EF restreint les appels pour séparer les instances DbContext des threads distincts? Il semble qu'il y ait une ressource partagée pour laquelle ils luttent.
- Y a-t-il quelque chose que je puisse faire pour améliorer le parallélisme dans ce cas?
MISE À JOUR
Pour la course en question, le degré maximum de parallélisme pour la tâche qui appelle SaveChanges est fixé à 12 (j'ai essayé différentes valeurs, y compris Unbounded dans les courses précédentes).
MISE A JOUR 2
équipe EF Microsoft a fourni des commentaires. Voir ma réponse pour un résumé.
Êtes-vous sûr que vous n'êtes pas en attente de connexions pour la piscine? Avez-vous essayé d'agrandir la taille de votre pool de connexion? – Maess
@Maess: Pour l'exécution en question, je mets le maximum de parallélisme à 12. Si je comprends bien, la taille maximale par défaut du pool de connexion est 100. Cependant, je vais essayer de le paramétrer explicitement plus haut. –
@Maess: Perfmon affiche seulement 11 connexions logiques et 11 connexions utilisateur à l'instance SQL, loin dans la limite du pool de connexions. –