Delen via


Casestudy: Een prestatieprobleem isoleren (C#, Visual Basic, F#)

Gebruik de profileringshulpprogramma's om prestatieproblemen te onderzoeken en probleemgebieden te isoleren. In deze casestudy wordt een voorbeeldtoepassing met prestatieproblemen gebruikt om te laten zien hoe u profileringshulpprogramma's gebruikt om de efficiëntie te verbeteren. Als u profileringsprogramma's wilt vergelijken, raadpleegt u Welk hulpprogramma moet ik kiezen?

In deze casestudy worden de volgende onderwerpen behandeld:

  • Visual Studio-profileringshulpprogramma's gebruiken om de prestaties van toepassingen te analyseren.
  • Hoe u de gegevens van deze hulpprogramma's interpreteert om prestatieknelpunten te identificeren.
  • Praktische strategieën toepassen om code te optimaliseren, gericht op .NET-tellers, aantal aanroepen en timinggegevens.

Volg de stappen en pas deze technieken vervolgens toe op uw eigen toepassingen om ze efficiënter en rendabeler te maken.

Een gevallenstudie van een prestatieprobleem isoleren

De voorbeeldtoepassing in deze casestudy is een ASP.NET-app die query's uitvoert op een gesimuleerde database. Het voorbeeld is gebaseerd op het voorbeeld van diagnostische gegevens.

Het primaire prestatieprobleem met de voorbeeldtoepassing ligt in inefficiënte coderingspatronen. De toepassing heeft een prestatieknelpunt dat de efficiëntie aanzienlijk beïnvloedt. Het probleem omvat de volgende symptomen:

  • laag CPU-gebruik: de toepassing geeft een laag CPU-gebruik weer, wat aangeeft dat de CPU niet het knelpunt is.

  • High ThreadPool Thread Count: het aantal threads is relatief hoog en neemt geleidelijk toe, wat duidt op een mogelijke uitputting van de threadpool.

  • trage toepassingsreactie: de toepassing reageert langzaam vanwege het ontbreken van beschikbare threads om nieuwe werkitems te verwerken.

De casestudy is erop gericht deze problemen op te lossen door de profileringshulpprogramma's van Visual Studio te gebruiken om de prestaties van de toepassing te analyseren. Door te begrijpen waar en hoe de prestaties van de toepassing kunnen worden verbeterd, kunnen ontwikkelaars optimalisaties implementeren om code sneller en efficiënter te maken. Het uiteindelijke doel is om de algehele prestaties van de toepassing te verbeteren, waardoor deze efficiënter en rendabeler kan worden uitgevoerd.

Uitdaging

Het oplossen van de prestatieproblemen in de .NET-voorbeeldtoepassing biedt verschillende uitdagingen. Deze uitdagingen komen voort uit de complexiteit van het diagnosticeren van prestatieknelpunten. De belangrijkste uitdagingen bij het oplossen van de beschreven problemen zijn als volgt:

  • prestatieknelpunten vaststellen: een van de belangrijkste uitdagingen is het nauwkeurig identificeren van de hoofdoorzaken van de prestatieproblemen. Een laag CPU-gebruik in combinatie met trage prestaties kan meerdere bijdragende factoren hebben. Ontwikkelaars moeten profileringshulpprogramma's effectief gebruiken om deze problemen vast te stellen. Hiervoor is enige kennis nodig van hoe deze hulpprogramma's werken en hoe ze hun uitvoer kunnen interpreteren.

  • kennis- en middelenbeperkingen: Teams kunnen te maken hebben met beperkingen met betrekking tot kennis, expertise en middelen. Profileren en optimaliseren van een toepassing vereist specifieke vaardigheden en ervaring, en niet alle teams hebben mogelijk onmiddellijk toegang tot deze resources.

Voor het aanpakken van deze uitdagingen is een strategische aanpak vereist die effectief gebruik combineert van profileringstools, technische kennis en zorgvuldige planning en testen. De casestudy is bedoeld om ontwikkelaars door dit proces te begeleiden, strategieën en inzichten te bieden om deze uitdagingen te overwinnen en de prestaties van de toepassing te verbeteren.

Strategie

Hier volgt een algemeen overzicht van de aanpak in deze casestudy:

  • We beginnen met het onderzoek door metrische gegevens van .NET-tellers te bekijken tijdens het verzamelen van prestatiegegevens. Net als het hulpprogramma CPU-gebruik is het hulpprogramma .NET Counters van Visual Studio ook een goed uitgangspunt voor een prestatieonderzoek.
  • Voor aanvullende inzichten om problemen te isoleren of de prestaties te verbeteren, kunt u overwegen om een tracering te verzamelen met behulp van een van de andere profileringshulpprogramma's. Bekijk bijvoorbeeld het aantal oproepen en tijdsgegevens met behulp van het instrumentatie hulpprogramma.

Voor het verzamelen van gegevens zijn de volgende taken vereist:

  • De app instellen op een release-build.
  • Selecteer de .NET Counters-tool in de Performance Profiler (Alt+F2). (Latere stappen omvatten het instrumentatiehulpmiddel.)
  • Start de app vanuit de Performance Profiler en verzamel een trace.

Prestatiemeters controleren

Tijdens het uitvoeren van de app zien we de tellers in het hulpprogramma .NET Counters. Voor eerste onderzoeken zijn enkele belangrijke metrische gegevens die u moet in de gaten houden:

  • CPU Usage. Bekijk deze prestatiemeter om te zien of er een prestatieprobleem optreedt bij hoog of laag CPU-gebruik. Dit kan een aanwijzing zijn voor specifieke typen prestatieproblemen. Bijvoorbeeld:
    • Met een hoog CPU-gebruik gebruikt u het hulpprogramma CPU-gebruik om gebieden te identificeren waar we mogelijk code kunnen optimaliseren. Zie voor een zelfstudie hierover Casestudy: Beginnershandleiding voor het optimaliseren van code.
    • Met een laag CPU-gebruik gebruikt u het hulpprogramma Instrumentatie om het aantal aanroepen en de gemiddelde functietijd te identificeren op basis van de kloktijd van de wand. Dit kan helpen bij het identificeren van problemen zoals conflicten of uitputting van de threadpool.
  • Allocation Rate. Voor een web-app die aanvragen verwerkt, moet de snelheid redelijk stabiel zijn.
  • GC Heap Size. Bekijk deze teller om te zien of het geheugengebruik voortdurend groeit en mogelijk lekt. Als het hoog lijkt, gebruikt u een van de hulpprogramma's voor geheugengebruik.
  • Threadpool Thread Count. Bekijk deze teller bij een webapplicatie om te zien of het aantal threads stabiel blijft of gestaag stijgt.

Hier volgt een voorbeeld van hoe de CPU Usage laag is, terwijl de ThreadPool Thread Count relatief hoog is.

Schermopname van tellers die worden weergegeven in het hulpprogramma .NET-tellers.

Een steeds stijgend aantal threads met een laag CPU-gebruik kan een indicator zijn van de starvatie van threadpools. De threadpool wordt gedwongen om constant nieuwe threads te starten. Threadpool-uitputting treedt op wanneer de pool geen voorhanden threads heeft om nieuwe werkopdrachten te verwerken en dit zorgt er vaak voor dat applicaties langzaam reageren.

Op basis van het lage CPU-gebruik en het relatief hoge aantal threads, en werkend vanuit de theorie van een mogelijk geval van uitputting van threadpools, schakelt u over naar het gebruik van het instrumentatiehulpprogramma.

Aantal oproepen en tijdsinstellingen onderzoeken

Laten we eens kijken naar een tracering van het hulpprogramma Instrumentatie om te zien of we meer kunnen proberen te ontdekken over wat er met de threads gebeurt.

Na het verzamelen van een tracering met het hulpprogramma Instrumentatie en het laden ervan in Visual Studio, controleren we eerst de eerste .diagsession rapportpagina met samengevatte gegevens. In de verzamelde trace gebruiken we de Details openen koppeling in het rapport en selecteren we vervolgens Flame Graph.

Schermopname van Flame Graph in het hulpprogramma Instrumentatie.

De Visualisatie van Flame Graph laat zien dat de QueryCustomerDB-functie (geel) verantwoordelijk is voor een aanzienlijk deel van de runtime van de app.

Klik met de rechtermuisknop op de functie QueryCustomerDB en kies Weergave in Aanroepstructuur.

Schermopname van oproepstructuur in het hulpprogramma Instrumentatie.

Het code-pad met het hoogste CPU-gebruik in de app wordt het hot pathgenoemd. Het vlamicoon voor Hot Path (Schermopname die het Hot Path-pictogram toont.) kan helpen om snel prestatieproblemen te identificeren die mogelijk kunnen worden verbeterd.

In de weergave Oproepstructuur ziet u dat het hot path de QueryCustomerDB-functie bevat, die verwijst naar een mogelijk prestatiesprobleem.

Ten opzichte van de tijd die in andere functies is besteed, zijn de Self- en Avg Self-waarden voor de functie QueryCustomerDB zeer hoog. In tegenstelling tot Totaal en Gem. Totaal, sluiten de zelfwaarden tijd in andere functies uit, dus dit is een geschikte plek om naar het prestatieknelpunt te zoeken.

Tip

Als de zelf- waarden relatief laag waren in plaats van hoog, zou u waarschijnlijk de werkelijke query's willen bekijken die door de QueryCustomerDB functie worden aangeroepen.

Dubbelklik op de functie QueryCustomerDB om de broncode voor de functie weer te geven.

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

We doen wat onderzoek. We kunnen ook tijd besparen en Copilot het onderzoek voor ons laten doen.

Als we Copilotgebruiken, selecteer Vraag aan Copilot in het contextmenu en typ de volgende vraag:

Can you identify a performance issue in the QueryCustomerDB method?

Fooi

U kunt slash-opdrachten zoals /optimize gebruiken om goede vragen voor Copilot te vormen.

Copilot vertelt ons dat deze code een asynchrone API aanroept zonder te wachten. Dit is het sync-over-async code patroon, dat een veelvoorkomende oorzaak is van threadpool-uitputting en threads kan blokkeren.

Gebruik "await" om het probleem op te lossen. In dit voorbeeld geeft Copilot de volgende codesuggesties samen met de uitleg.

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

Als u prestatieproblemen met betrekking tot databasequery's ziet, kunt u het hulpprogramma Database gebruiken om te onderzoeken of bepaalde aanroepen trager zijn. Deze gegevens kunnen wijzen op een mogelijkheid om query's te optimaliseren. Voor een tutorial die laat zien hoe u het hulpprogramma Database kunt gebruiken om een prestatieprobleem te onderzoeken, zie Case study: Beginner's guide to optimizing code. De databasetool ondersteunt .NET Core met zowel ADO.NET als Entity Framework Core.

Als u visualisaties in Visual Studio wilt ophalen voor het gedrag van afzonderlijke threads, kunt u het venster Parallel Stacks gebruiken tijdens foutopsporing. In dit venster worden afzonderlijke threads weergegeven, samen met informatie over threads die wachten, threads waarop ze wachten en deadlocks.

Zie Detecteren van threadpool-uitputtingvoor meer informatie over threadpool-uitputting.

Volgende stappen

De volgende artikelen en blogposts bieden meer informatie om u te helpen de Visual Studio-prestatiehulpprogramma's effectief te gebruiken.