2011-06-23 3 views
12

J'ai configuré mvc-mini-profiler sur mon site MVC 3 équipé d'Entity Framework. Tout est dûment configuré; Démarrage du profilage dans Application_Start, fin dans Application_End et ainsi de suite. La partie profilage fonctionne très bien. Cependant, lorsque j'essaie d'échanger ma génération d'objet de modèle de données pour fournir des versions profilables, les performances ralentissent. Pas toutes les requêtes SQL, mais certaines requêtes prennent environ 5 fois le chargement de la page entière. (Le chargement de la première page après avoir allumé IIS Express prend un peu plus de temps, mais il est maintenu.)mvc-mini-profiler ralentit Entity Framework

Temps négligeable (~ 2ms) est passé à interroger, exécuter et "lire des données" le SQL, alors que cette ligne:

var person = dataContext.People.FirstOrDefault(p => p.PersonID == id); 

... quand enveloppé dans using(profiler.Step()) est enregistré comme prenant 300-400 ms. J'ai profilé avec dotTrace, qui a confirmé que le temps est réellement passé en EF comme d'habitude (les composants profilables font des apparitions très brèves), seulement cela prend beaucoup plus de temps. Cela me porte à croire que la connexion ou certaines de ses parties constituantes manquent de données suffisantes, ce qui rend les performances EF bien pire.

C'est ce que j'utilise pour faire l'objet de contexte (ma classe de modèle edmx est appelé DataContext):

var conn = ProfiledDbConnection.Get(
    /* returns an SqlConnection */CreateConnection()); 
return CreateObjectContext<DataContext>(conn); 

I utilisé à l'origine du mvc-mini-profileur fourni méthode ObjectContextUtils.CreateObjectContext. J'y ai plongé et j'ai remarqué qu'il définissait une chaîne de chemin d'accès à l'espace de travail des métadonnées génériques. Comme j'ai la couche de base de données isolée à un projet et plusieurs sites MVC comme d'autres projets utilisant le code, ces chemins ont changé et je préfère être plus spécifique. En outre, je pensais que c'était la cause du problème de performance. Je la fonctionnalité CreateObjectContext dupliqué dans mon propre projet de fournir ce, en tant que tel:

public static T CreateObjectContext<T>(DbConnection connection) where T : System.Data.Objects.ObjectContext { 
     var workspace = new System.Data.Metadata.Edm.MetadataWorkspace(
      GetMetadataPathsString().Split('|'), 
      // ^-- returns 
      // "res://*/Redacted.csdl|res://*/Redacted.ssdl|res://*/Redacted.msl" 
      new Assembly[] { typeof(T).Assembly }); 

     // The remainder of the method is copied straight from the original, 
     // and I carried over a duplicate CtorCache too to make this work. 
     var factory = DbProviderServices.GetProviderFactory(connection); 
     var itemCollection = workspace.GetItemCollection(System.Data.Metadata.Edm.DataSpace.SSpace); 
     itemCollection.GetType().GetField("_providerFactory", // <==== big fat ugly hack 
      BindingFlags.NonPublic | BindingFlags.Instance).SetValue(itemCollection, factory); 
     var ec = new System.Data.EntityClient.EntityConnection(workspace, connection); 
     return CtorCache<T, System.Data.EntityClient.EntityConnection>.Ctor(ec); 
    } 

... mais il ne semble pas faire beaucoup de différence. Le problème persiste si j'utilise la version piratée ci-dessus qui est plus spécifique avec les chemins d'accès à l'espace de travail de métadonnées ou la version fournie par mvc-mini-profiler. Je pensais juste que je mentionnerais que j'ai aussi essayé.

Ayant épuisé tout cela, je suis à bout de nerfs. Encore une fois: lorsque je fournis mon contexte de données comme d'habitude, aucune performance n'est perdue. Lorsque je fournis un contexte de données "profilable", les performances dégringolent pour certaines requêtes (je ne sais pas non plus ce qui influence cela). Qu'est-ce que mvc-mini-profiler peut faire? Est-ce que je continue de lui donner les mauvaises données? Je pense que c'est le même problème que rencontré this person.

+0

Je suis celui qui a le même problème sur le lien que vous avez fourni. J'espère que nous pouvons trouver une solution. – WVDominick

+0

J'ai transmis cela à l'équipe EF ... j'espère que nous aurons des conseils –

+0

@Sam: Awesome. Merci. – Jesper

Répondre

4

Je viens de résoudre ce problème aujourd'hui.

voir: http://code.google.com/p/mvc-mini-profiler/issues/detail?id=43

Il est arrivé causer certains de nos hacks de fantaisie ont été mises en cache pas assez bien.En particulier:

var workspace = new System.Data.Metadata.Edm.MetadataWorkspace(
    new string[] { "res://*/" },  
    new Assembly[] { typeof(T).Assembly }); 

Est un appel très coûteux, nous avons donc besoin de mettre en cache l'espace de travail.

+0

Nice. J'ai parcouru votre code auparavant et j'ai complètement raté ça. –

+0

Cela semble prometteur. Acceptera si cela fonctionne. – Jesper

+0

Cela l'a résolu. Merci! Maintenant, je suis en train de lutter contre le conflit de verrouillage de l'état de la session en ajoutant 500 ms entre le démarrage du profileur et le démarrage de MVC. Le plaisir ne finit jamais. – Jesper

-2

Le profilage, by definition, affectera les performances de l'application à profiler. Le profileur doit insérer ses propres appels de méthode dans l'application, intercepter les appels système de bas niveau et enregistrer toutes ces données quelque part (c'est-à-dire écrire sur le disque). Toutes ces tâches occupent des cycles de processeur, de la mémoire et un accès au disque précieux.

+1

Oh, bien sûr, je comprends cela et je suis confortablement à l'aise avec ce compromis, mais c'est une augmentation spectaculaire dans un petit spectre d'opérations apparemment triviales. Ce n'est pas non plus le cas que la performance diminue de manière égale ou à peu près égale dans tous les domaines. Certaines requêtes qui matérialisent beaucoup plus d'objets sont également beaucoup plus rapides. Ceci est reproductible clairement une valeur aberrante, pour apparemment pas de raison. – Jesper

+0

Avez-vous essayé l'un des outils de profilage génériques à la place, pour voir s'ils présentent les mêmes problèmes de performance? – RyanR

+0

Oui; la question indique que j'ai utilisé dotTrace pour localiser le chemin chaud pendant l'installation de ce profileur. (L'exécution a ralenti partout.) La question est de savoir en quoi cela n'a pas de sens et comment j'espère que je n'ai pas tout arrangé correctement. mvc-mini-profiler n'est pas vraiment un profiler selon la définition commune car il ne touche pas à tout pour instrumentaliser l'exécution, mais il répond à un besoin difficile à satisfaire autrement (visiter son site pour un traité plus profond) Je serais très heureux si je devais seulement atteindre dotTrace quand quelque chose appelle l'artillerie lourde. – Jesper