Fallstudie: Isolieren eines Leistungsproblems (C#, Visual Basic, F#)
Verwenden Sie die Profilerstellungstools, um Leistungsprobleme zu untersuchen und Problembereiche zu isolieren. In dieser Fallstudie wird eine Beispielanwendung mit Leistungsproblemen verwendet, um zu veranschaulichen, wie Sie Profilerstellungstools verwenden, um die Effizienz zu verbessern. Wenn Sie Profilerstellungstools vergleichen möchten, lesen Sie Welches Tool sollte ich auswählen?
In dieser Fallstudie werden die folgenden Themen behandelt:
- Wie man die Profiling-Tools von Visual Studio zur Analyse der Anwendungsleistung verwendet.
- So interpretieren Sie die von diesen Tools bereitgestellten Daten, um Leistungsengpässe zu identifizieren.
- So wenden Sie praktische Strategien zum Optimieren von Code an, wobei sie sich auf .NET-Leistungsindikatoren, Anrufanzahlen und Zeitangaben konzentrieren.
Folgen Sie diesen Techniken, und wenden Sie diese Techniken dann auf Ihre eigenen Anwendungen an, um sie effizienter und kostengünstiger zu gestalten.
Fallstudie zum Isolieren eines Leistungsproblems
Die Beispielanwendung in dieser Fallstudie ist eine ASP.NET-App, die Abfragen für eine simulierte Datenbank ausführt. Das Beispiel basiert auf dem Diagnosebeispiel.
Das primäre Leistungsproblem mit der Beispielanwendung liegt in ineffizienten Codierungsmustern. Die Anwendung hat einen Leistungsengpass, der sich erheblich auf ihre Effizienz auswirkt. Das Problem umfasst die folgenden Symptome:
niedrige CPU-Auslastung: Die Anwendung zeigt eine niedrige CPU-Auslastung an, die angibt, dass die CPU nicht der Engpass ist.
High ThreadPool Thread Count: Die Threadanzahl ist relativ hoch und steigt stetig an, was auf einen möglichen Threadpoolmangel hindeutet.
Langsame Anwendungsantwort: Die Anwendung reagiert langsam, da keine verfügbaren Threads zum Verarbeiten neuer Arbeitsaufgaben vorhanden sind.
Die Fallstudie zielt darauf ab, diese Probleme zu beheben, indem die Profilerstellungstools von Visual Studio verwendet werden, um die Leistung der Anwendung zu analysieren. Indem Sie verstehen, wo und wie die Leistung der Anwendung verbessert werden kann, können Entwickler Optimierungen implementieren, um Code schneller und effizienter zu gestalten. Das ultimative Ziel ist es, die Gesamtleistung der Anwendung zu verbessern, sodass sie effizienter und kostengünstiger ausgeführt werden kann.
Herausforderung
Die Behandlung der Leistungsprobleme in der .NET-Beispielanwendung stellt mehrere Herausforderungen dar. Diese Herausforderungen ergeben sich aus der Komplexität der Diagnose von Leistungsengpässen. Die wichtigsten Herausforderungen bei der Behebung der beschriebenen Probleme sind wie folgt:
Diagnose von Leistungsengpässen: Eine der wichtigsten Herausforderungen ist die genaue Identifizierung der Ursachen der Leistungsprobleme. Geringe CPU-Auslastung in Kombination mit langsamer Leistung kann mehrere Faktoren haben. Entwickler müssen Profilerstellungstools effektiv verwenden, um diese Probleme zu diagnostizieren, was ein gewisses Verständnis dafür erfordert, wie diese Tools funktionieren und wie sie ihre Ausgabe interpretieren können.
Wissens- und Ressourceneinschränkungen: Teams kann Einschränkungen im Zusammenhang mit Wissen, Fachwissen und Ressourcen aufweisen. Die Profilerstellung und Optimierung einer Anwendung erfordert spezifische Fähigkeiten und Erfahrungen, und nicht alle Teams haben möglicherweise sofortigen Zugriff auf diese Ressourcen.
Die Bewältigung dieser Herausforderungen erfordert einen strategischen Ansatz, der eine effektive Verwendung von Profilerstellungstools, technischem Wissen und sorgfältiger Planung und Tests kombiniert. Die Fallstudie zielt darauf ab, Entwickler durch diesen Prozess zu führen, Strategien und Erkenntnisse bereitzustellen, um diese Herausforderungen zu überwinden und die Leistung der Anwendung zu verbessern.
Strategie
Hier ist eine generelle Übersicht der Vorgehensweise in dieser Fallstudie:
- Wir starten die Untersuchung, indem wir .NET-Leistungsmetriken beobachten, während wir Leistungsdaten sammeln. Wie das Tool für die CPU-Auslastung ist auch die .NET Counters Tool von Visual Studio ein guter Ausgangspunkt für eine Leistungsuntersuchung.
- Wenn Sie dann zusätzliche Erkenntnisse benötigen, um Probleme zu isolieren oder die Leistung zu verbessern, sollten Sie eine Ablaufverfolgung mithilfe eines der anderen Profilerstellungstools erfassen. Sehen Sie sich beispielsweise die Anrufanzahl und die Timing-Daten mithilfe des Tools Instrumentation an.
Für die Datensammlung sind die folgenden Aufgaben erforderlich:
- Festlegen der App auf einen Release-Build.
- Wählen Sie das .NET Counters-Tool aus dem Performance Profiler (ALT+F2). (Spätere Schritte umfassen das Instrumentierungstool.)
- Starten Sie die App im Leistungsprofiler, und erfassen Sie eine Ablaufverfolgung.
Leistungszähler überprüfen
Während der Ausführung der App beobachten wir die Zähler im .NET Counters-Tool. Für erste Untersuchungen sollten einige wichtige Kennzahlen im Auge behalten werden:
CPU Usage
. Schauen Sie sich diesen Leistungsindikator an, um festzustellen, ob ein Leistungsproblem mit hoher oder geringer CPU-Auslastung auftritt. Dies kann ein Hinweis auf bestimmte Arten von Leistungsproblemen sein. Zum Beispiel:- Verwenden Sie bei hoher CPU-Auslastung das TOOL FÜR die CPU-Auslastung, um Bereiche zu identifizieren, in denen wir Code möglicherweise optimieren können. Ein Lernprogramm hierzu finden Sie in Fallstudie: Anfängerleitfaden zur Optimierung von Code.
- Verwenden Sie bei geringer CPU-Auslastung das Instrumentierungstool, um die Anrufanzahl und die durchschnittliche Funktionszeit basierend auf der Wanduhrzeit zu identifizieren. Dies kann dazu beitragen, Probleme wie z. B. Konflikte oder das Verhungern des Threadpools zu erkennen.
Allocation Rate
. Für eine Web-App, die Anforderungen bedient, sollte die Rate relativ stabil sein.GC Heap Size
. Sehen Sie sich diesen Zähler an, um zu überprüfen, ob die Speicherauslastung kontinuierlich zunimmt und potenziell undicht wird. Wenn es hoch erscheint, verwenden Sie eines der Speichernutzungstools.Threadpool Thread Count
. Für eine Web-App, die Anforderungen bedient, sehen Sie sich diesen Indikator an, um festzustellen, ob die Threadanzahl konstant oder stetig steigt.
Hier ist ein Beispiel, das zeigt, wie die CPU Usage
niedrig ist, während die ThreadPool Thread Count
relativ hoch ist.
Eine stetig steigende Threadanzahl mit einer niedrigen CPU-Auslastung kann ein Indikator für den Hunger des Threadpools sein. Der Threadpool wird gezwungen, ständig neue Threads zu erstellen. Threadpool-Starvation tritt auf, wenn der Pool keine verfügbaren Threads zum Verarbeiten neuer Arbeitsaufgaben hat und häufig dazu führt, dass Anwendungen langsam reagieren.
Basierend auf der niedrigen CPU-Auslastung und der relativ hohen Threadanzahl sowie der Theorie eines möglichen Threadpoolmangels sollten Sie zum Instrumentierungstool wechseln.
Untersuchung der Anrufanzahlen und Zeitdaten
Sehen wir uns eine Ablaufverfolgung des Instrumentierungstools an, um zu sehen, ob wir mehr darüber erfahren, was mit den Threads passiert.
Nach dem Sammeln einer Ablaufverfolgung mit dem Instrumentierungstool und dem Laden in Visual Studio überprüfen wir zuerst die anfängliche .diagsession-Berichtsseite, die zusammengefasste Daten anzeigt. In der erfassten Ablaufverfolgung verwenden wir den Link Details öffnen im Bericht und wählen dann Flame-Diagramm aus.
Die Flame Graph-Visualisierung zeigt uns, dass die QueryCustomerDB
-Funktion (in Gelb dargestellt) für einen erheblichen Teil der Laufzeit der App verantwortlich ist.
Klicken Sie mit der rechten Maustaste auf die QueryCustomerDB
-Funktion, und wählen Sie In Aufrufstruktur anzeigen aus.
Der Codepfad mit der höchsten CPU-Auslastung in der App wird als hot pathbezeichnet. Das Symbol "Hot Path-Flamme" () kann dazu beitragen, Leistungsprobleme schnell zu erkennen, die möglicherweise verbessert werden.
In der Ansicht Aufrufstruktur können Sie sehen, dass der Hot-Path die QueryCustomerDB
-Funktion enthält, die auf ein potenzielles Leistungsproblem verweist.
Relativ zur Zeit, die in anderen Funktionen verbracht wurde, sind die Self und Avg Self Werte für die QueryCustomerDB
Funktion sehr hoch. Im Gegensatz zu Total und Avg Totalschließen die Self-Werte die in anderen Funktionen aufgewendete Zeit aus, sodass dies ein guter Punkt ist, um den Leistungsengpass zu identifizieren.
Tipp
Wenn die Self-Werte relativ niedrig statt hoch waren, sollten Sie wahrscheinlich die tatsächlichen Abfragen betrachten, die von der QueryCustomerDB
-Funktion aufgerufen werden.
Doppelklicken Sie auf die QueryCustomerDB
-Funktion, um den Quellcode für die Funktion anzuzeigen.
public ActionResult<string> QueryCustomerDB()
{
Customer c = QueryCustomerFromDbAsync("Dana").Result;
return "success:taskwait";
}
Wir recherchieren ein wenig. Alternativ können wir Zeit sparen und Copilot die Forschung für uns durchführen lassen.
Wenn wir Copilotverwenden, wählen Sie im Kontextmenü "Copilot fragen" aus, und geben Sie die folgende Frage ein:
Can you identify a performance issue in the QueryCustomerDB method?
Tipp
Sie können Schrägstrichbefehle wie /optimize verwenden, um gute Fragen für Copilot zu bilden.
Copilot teilt uns mit, dass dieser Code eine asynchrone API aufruft, ohne await zu verwenden. Dies ist das sync-over-async-Codemuster, das eine häufige Ursache für das Verhungern des Threadpools ist und Threads blockieren kann.
Um das Problem zu lösen, verwenden Sie "await". In diesem Beispiel gibt Copilot den folgenden Codevorschlag zusammen mit der Erläuterung.
public async Task<ActionResult<string>> QueryCustomerDB()
{
Customer c = await QueryCustomerFromDbAsync("Dana");
return "success:taskwait";
}
Wenn Leistungsprobleme im Zusammenhang mit Datenbankabfragen angezeigt werden, können Sie das Datenbanktool verwenden, um zu untersuchen, ob bestimmte Aufrufe langsamer sind. Diese Daten können auf eine Möglichkeit zum Optimieren von Abfragen hinweisen. Ein Lernprogramm, das zeigt, wie Sie mithilfe des Datenbanktools ein Leistungsproblem untersuchen können, finden Sie in Fallstudie: Leitfaden für Anfänger zum Optimieren von Code. Das Datenbanktool unterstützt .NET Core entweder mit ADO.NET oder Entity Framework Core.
Um Visualisierungen in Visual Studio für das einzelne Threadverhalten abzurufen, können Sie das fenster Parallel Stacks beim Debuggen verwenden. Dieses Fenster zeigt einzelne Threads zusammen mit Informationen zu Threads, die warten, Threads, auf die sie warten, und Deadlocks.
Weitere Informationen zum Threadpoolmangel finden Sie unter Erkennen eines Mangels im ThreadPool.
Nächste Schritte
Die folgenden Artikel und Blogbeiträge enthalten weitere Informationen, die Ihnen helfen, die Visual Studio-Leistungstools effektiv zu verwenden.
- Fallstudie: Leitfaden für Anfänger zur Optimierung von Code
- Fallstudie: Doppelte Leistung in weniger als 30 Minuten
- Verbessern der Visual Studio-Leistung mit dem neuen Instrumentierungstool