14

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é.

+1

Ê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

+0

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

+0

@Maess: Perfmon affiche seulement 11 connexions logiques et 11 connexions utilisateur à l'instance SQL, loin dans la limite du pool de connexions. –

Répondre

5

Ce qui suit résume mon interaction avec l'équipe Entity Framework sur ce problème.Je mettrai à jour la réponse si plus d'information devient disponible

  • Le problème peut être reproduit chez Microsoft.
  • La contention du handle est liée à l'E/S réseau (même avec SQL Server sur localhost). Plus précisément, il existe une contention pour le tampon de lecture pour Network I/O dans System.Data.dll.
  • L'équipe EF travaille maintenant avec l'équipe de connectivité SQL pour mieux comprendre le problème.
  • Il n'y a pas encore d'indications de Microsoft sur la façon de minimiser l'impact de cette contention.

MISE À JOUR

Ce problème est en cours de suivi sur CodePlex:

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

+0

Merci beaucoup Eric. Je suis très intéressé par ce coz j'ai un scénario similaire. Avons-nous un problème pour cela sur connect.microsoft.com afin que nous puissions suivre sa progression? – Dodd

+0

@Dodd: Il est suivi sur Codeplex depuis EF est open source maintenant (mais toujours travaillé par l'équipe de Microsoft). Ajouté le lien –