Udostępnij przez


Analiza przypadku: Izolowanie problemu z wydajnością (C#, Visual Basic, F#)

W tym badaniu przypadku pokazano, jak używać narzędzi profilowania programu Visual Studio do identyfikowania i rozwiązywania problemów z wydajnością w przykładowej aplikacji ASP.NET. Aby zapoznać się z porównaniem narzędzi profilowania, zobacz Jakie narzędzie należy wybrać?

Dowiesz się:

  • Jak używać narzędzi profilowania programu Visual Studio do analizowania wydajności aplikacji.
  • Jak interpretować dane profilowania w celu znalezienia wąskich gardeł.
  • Praktyczne strategie optymalizacji kodu przy użyciu liczników platformy .NET, liczników wywołań i danych chronometrażu.

Zastosuj te techniki, aby ulepszyć własne aplikacje.

Wydziel przypadek opisujący problem z wydajnością

Przykładowa aplikacja ASP.NET uruchamia zapytania względem symulowanej bazy danych i jest oparta na przykładzie diagnostyki.

Kluczowe objawy wydajności:

  • Niskie użycie procesora: Procesor nie stanowi wąskiego gardła.
  • Duża liczba wątków w puli wątków: liczba wątków stale rośnie, co wskazuje na głodowanie puli wątków.
  • Powolna odpowiedź aplikacji: aplikacja działa wolno z powodu braku dostępnych wątków.

W tym badaniu przypadku używane są narzędzia profilowania programu Visual Studio w celu zidentyfikowania i rozwiązania tych problemów, co ułatwia szybsze i wydajniejsze tworzenie kodu.

Wyzwanie

Rozwiązanie tych problemów wiąże się z kilkoma wyzwaniami:

  • Diagnozowanie wąskich gardeł: niskie użycie CPU przy wolnym działaniu może mieć wiele przyczyn. Skuteczne korzystanie z narzędzi profilowania i interpretowanie ich danych wyjściowych jest niezbędne.
  • Ograniczenia wiedzy i zasobów: profilowanie i optymalizacja wymagają określonych umiejętności i doświadczenia, które mogą nie zawsze być dostępne.

Strategiczne podejście łączące narzędzia profilowania, wiedzę techniczną i staranne testowanie jest kluczem do przezwyciężenia tych wyzwań.

Strategia

Oto ogólny widok podejścia w tym badaniu przypadku:

  • Zacznij od monitorowania metryk liczników platformy .NET podczas zbierania danych dotyczących wydajności. Narzędzie liczników .NET programu Visual Studio jest dobrym punktem wyjścia.
  • Aby uzyskać bardziej szczegółowe informacje, zbierz ślady za pomocą dodatkowych narzędzi profilowania, takich jak narzędzie instrumentacji do obsługi liczników wywołań i danych o chronometrażu.

Zbieranie danych wymaga następujących zadań:

  • Ustaw aplikację na Release build (Wydanie kompilacji).
  • Wybierz narzędzie Liczniki platformy .NET w profilerze wydajności (Alt+F2).
  • Uruchom aplikację i zbierz ślad.

Sprawdzanie liczników wydajności

Podczas uruchamiania aplikacji obserwujemy liczniki w narzędziu Liczniki platformy .NET. W przypadku wstępnych badań warto zwrócić uwagę na kilka kluczowych metryk, takich jak:

  • CPU Usage. Obejrzyj ten licznik, aby sprawdzić, czy wysoki lub niski poziom wykorzystania procesora powoduje problem z wydajnością. Może to być wskazówka dla konkretnych typów problemów z wydajnością. Na przykład:
    • Przy wysokim użyciu CPU, użyj narzędzia Użycie procesora, aby zidentyfikować obszary, w których możemy zoptymalizować kod. Aby zapoznać się z tym samouczkiem, zobacz Analiza przypadku: Przewodnik dla początkujących dotyczący optymalizowania kodu.
    • Przy niskim użyciu procesora CPU użyj narzędzia Instrumentacja, aby zidentyfikować liczby wywołań i średni czas funkcji na podstawie czasu zegara ściany. Może to pomóc w zidentyfikowaniu problemów, takich jak zawężenie lub wyczerpanie puli wątków.
  • Allocation Rate. Dla aplikacji internetowej obsługującej żądania tempo powinno być dość stabilne.
  • GC Heap Size. Obejrzyj ten licznik, aby sprawdzić, czy użycie pamięci stale rośnie i potencjalnie przecieka. Jeśli wydaje się to wysokie, użyj jednego z narzędzi do użycia pamięci.
  • Threadpool Thread Count. Aby obsłużyć żądania w aplikacji internetowej, obserwuj ten licznik, aby sprawdzić, czy liczba wątków utrzymuje się na stałym poziomie lub rośnie w stałym tempie.

Oto przykład pokazujący, jak CPU Usage jest niska, a ThreadPool Thread Count jest stosunkowo wysoka.

Zrzut ekranu przedstawiający liczniki wyświetlane w narzędziu Liczniki platformy .NET.

Ciągle rosnąca liczba wątków przy niskim użyciu procesora może być wskaźnikiem głodu puli wątków. Wątkowa pula jest zmuszona do tworzenia nowych wątków. Głodowanie puli wątków występuje, gdy pula nie ma dostępnych wątków do przetwarzania nowych elementów roboczych i często powoduje powolne reagowanie aplikacji.

Na podstawie niskiego użycia procesora i stosunkowo dużej liczby wątków oraz pracy nad teorią możliwego przypadku zablokowania puli wątków, przejdź na używanie narzędzia Instrumentacja.

Badanie liczby wywołań i danych dotyczących czasu

Przyjrzyjmy się śladowi z narzędzia Instrumentacja, aby dowiedzieć się więcej o tym, co dzieje się z wątkami.

Po zebraniu śladu za pomocą narzędzia Instrumentacja i załadowaniu go do programu Visual Studio, przede wszystkim sprawdzamy początkową stronę raportu .diagsession, która zawiera podsumowane dane. W zebranym śladzie korzystamy z linku Otwórz szczegóły w raporcie, a następnie wybieramy Flame Graph.

zrzut ekranu przedstawiający wykres płomieniowy w narzędziu Instrumentacja.

Wizualizacja Flame Graph pokazuje, że funkcja QueryCustomerDB (pokazana na żółto) jest odpowiedzialna za znaczną część czasu działania aplikacji.

Kliknij prawym przyciskiem myszy funkcję QueryCustomerDB i wybierz pozycję widok w drzewie wywołań.

zrzut ekranu przedstawiający drzewo wywołań w narzędziu Instrumentacja.

Ścieżka kodu o najwyższym użyciu procesora CPU w aplikacji jest nazywana ścieżką gorącą . Ikona płomienia ścieżki gorącej (Zrzut ekranu przedstawiający ikonę Ścieżka gorąca.) może pomóc w szybkim zidentyfikowaniu problemów z wydajnością, które mogą zostać ulepszone.

W widoku drzewa wywołań widać, że ścieżka gorąca zawiera funkcję QueryCustomerDB, która wskazuje na potencjalny problem z wydajnością.

W stosunku do czasu spędzonego w innych funkcjach wartości Self i Avg Self dla funkcji QueryCustomerDB są bardzo wysokie. W przeciwieństwie do wartości Total i Avg Total, wartości Self wykluczają czas spędzony w innych funkcjach, dlatego jest to dobre miejsce, aby wyszukać wąskie gardło wydajności.

Napiwek

Jeśli wartości Self były stosunkowo niskie, a nie wysokie, prawdopodobnie warto przyjrzeć się rzeczywistym zapytaniom wywoływanym przez funkcję QueryCustomerDB.

Kliknij dwukrotnie funkcję QueryCustomerDB, aby wyświetlić kod źródłowy funkcji.

public ActionResult<string> QueryCustomerDB()
{
    Customer c = QueryCustomerFromDbAsync("Dana").Result;
    return "success:taskwait";
}

Robimy trochę badań. Alternatywnie możemy zaoszczędzić czas i pozwolić Copilot zrobić badania dla nas.

Jeśli używamy Copilot , wybierz pozycję Ask Copilot z menu kontekstowego i wpisz następujące pytanie:

Can you identify a performance issue in the QueryCustomerDB method?

Napiwek

Możesz użyć poleceń ze znakiem ukośnika, takich jak /optimize, aby pomóc w tworzeniu dobrych pytań dotyczących Copilot.

Copilot informuje nas, że ten kod wywołuje asynchroniczny interfejs API bez użycia funkcji await. Jest to wzorzec kodu sync-over-async, który jest częstą przyczyną wyczerpania zasobów puli wątków i może prowadzić do blokowania wątków.

Aby rozwiązać ten problem, użyj funkcji await. W tym przykładzie copilot udostępnia następującą sugestię kodu wraz z wyjaśnieniem.

public async Task<ActionResult<string>> QueryCustomerDB()
{
    Customer c = await QueryCustomerFromDbAsync("Dana");
    return "success:taskwait";
}

Jeśli widzisz problemy z wydajnością związane z zapytaniami bazy danych, możesz użyć narzędzia Database w celu zbadania, czy niektóre wywołania są wolniejsze. Te dane mogą wskazywać na możliwość optymalizacji zapytań. Aby zapoznać się z samouczkiem pokazującym, jak za pomocą narzędzia Baza danych zbadać problem z wydajnością, zobacz Analiza przypadku: Przewodnik dla początkujących dotyczący optymalizowania kodu. Narzędzie do baz danych obsługuje platformę .NET Core z ADO.NET lub Entity Framework Core.

Aby uzyskać wizualizacje w programie Visual Studio dla zachowania poszczególnych wątków, możesz użyć okna Parallel Stacks podczas debugowania. W tym oknie są wyświetlane poszczególne wątki wraz z informacjami o wątkach, które oczekują, wątkach, na które czekają, oraz zakleszczenia.

Aby uzyskać dodatkowe informacje na temat głodu puli wątków, zobacz Wykrywanie głodu puli wątków.

Następne kroki

Poniższe artykuły i wpisy w blogu zawierają więcej informacji, aby ułatwić efektywne korzystanie z narzędzi do wydajności programu Visual Studio.