2014-04-29 1 views
6

Wir versuchen derzeit, die Leistung unserer Entity Framework-Abfragen zu optimieren. Insbesondere suchen wir nach Möglichkeiten, die CPU-Auslastung zu reduzieren.EF Performance: ComputeHashValue() in der Kompilierung von Abfragen

Mit dotTrace haben wir analysiert, was die meiste CPU-Zeit beim Ausführen verschiedener Abfragen kostet. Siehe den folgenden Schnappschuss: dotTrace Call Tree

Dieser Schnappschuss stammt aus einer ziemlich einfachen Abfrage, zeigt aber immer noch, welche die zeitaufwendigste Operation ist: GetExecutionPlan(). Dringt man noch weiter hinein, so sieht man, dass in der Methode ComputeHashValue(), die für alle Knoten in der Ausdrucksbaumstruktur rekursiv aufgerufen wird, viel Zeit in Anspruch genommen wird.

This blog post besagt, dass

Das Entity Framework wird die Knoten im Ausdrucksbaum gehen und einen Hash erzeugen, die der Schlüssel platzieren Sie es in der Abfrage Cache verwendet wird.

So scheint es, dass die Hash-Werte nur als Schlüssel für den Abfrage-Cache verwendet werden. Da wir IEnumerable.Contains verwenden() in unsere Anfragen, EF sie nicht Chache (this MSDN article (chapters 3.2 & 4.1) sehen Deshalb haben wir deaktiviert Query Plan Caching wie folgt:.

var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext; 
var objectSet = objectContext.CreateObjectSet<Customer>(); 
objectSet.EnablePlanCaching = false; 
// use objectSet for queries.. 

Wir hoffen, dass dann ComputeHashValue() nicht aufgerufen werden mehr. es gibt jedoch in der Aufrufstruktur keine Änderung von dotTrace und Leistung war identisch gezeigt wurde, wie mit Query Plan Caching aktiviert.

gibt es einen Grund, warum ComputeHashValue() immer noch, wenn Query Plan benötigt wird Caching deaktiviert ist?

Bei komplexeren Abfragen benötigen alle Aufrufe von ComputeHashValue() bis zu 70% der gesamten CPU Zeit, die für die Ausführung der Abfrage benötigt wird. Diese Aufrufe zu vermeiden (wenn sie nicht benötigt werden) würde unsere Leistung massiv beeinträchtigen.

+0

Nach dem Screenshot fast keine Zeit dort verbracht. Ist dieses Profil nicht repräsentativ für Ihre Arbeitsbelastung? – usr

+1

Die 3 Aufrufe werden hier mit 0ms bezeichnet. Aber ComputeHashValue() wird für jeden Knoten im Ausdrucksbaum aufgerufen, was insgesamt zu Hunderten von Aufrufen führt und fast alle der 93ms werden von ihnen verwendet. Sie können die verschiedenen rekursiven Aufrufe von ApplyRulesToSubtree() sehen, die letztendlich zu Aufrufen von ComputeHashValue() führen. –

Antwort

0

Leider wurde das Entity Framework nicht implementiert. Ich habe mich ein wenig mit dem Quellcode befasst und mein Verständnis ist, dass es sowieso einen ExecutionPlan kompiliert, es berechnet auch HashValue. Dies ist der Fall, wenn EnablePlanCaching aktiviert ist und eine zwischengespeicherte Abfrage nicht gefunden werden konnte. Sie kann sie dann basierend auf diesem ComputedValue zum Cache-Manager hinzufügen. Hier

ist ein Link zu der Klasse, die diese Logik behandelt: EntitySqlQueryState

+0

Nachdem wir den Quellcode ([ELinqQueryState] (http://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework/Core/Objects/ELinq/ELinqQueryState.cs), da wir Linq2Entities verwenden, genauer betrachtet haben, Ich denke, dass diese Aufrufe von 'ComputeHashValue()' nicht zum Generieren des Cache-Schlüssels verwendet werden. Der 'cacheKey' wird zuerst generiert (mit' ExpressionKeyGen.TryGenerateKey() 'und danach wird der Ausführungsplan erstellt (Aufruf an' _objectQueryExecutionPlanFactory.Prepare() '.) So scheint es, dass' ComputeHashValue() 'immer benötigt wird ob das Planen von Caching aktiviert ist oder nicht –

+0

Das habe ich versucht zu erklären :).Ich habe auch viele MergeOption-Parameter gesehen. Haben Sie versucht, MergeOption.NoTracking zu verwenden, indem Sie 'AsNoTracking()' LINQ-Methode aufrufen und sehen, was der Leistungsunterschied dann ist? [AsNoTracking] (http://msdn.microsoft.com/en-us/library/gg679352 (v = vs.103) .aspx) –

+0

AsNoTracking() macht keinen Unterschied. MergeOption wird nur verwendet, um zu überprüfen, ob der zwischengespeicherte Abfrageplan wiederverwendet werden kann: "Wenn eine Zusammenführungsoption explizit angegeben wurde und nicht mit der Zusammenführungsoption des Plans übereinstimmt, ist der Plan nicht mehr gültig." –

Verwandte Themen