Felsöka hög CPU-användning i .NET Core

Den här artikeln gäller för: ✔️ .NET Core 3.1 SDK och senare versioner

I den här självstudien får du lära dig hur du felsöker ett scenario med överdriven CPU-användning. Med hjälp av det angivna exemplet ASP.NET Källkodslagringsplats för Core-webbappen kan du avsiktligt orsaka ett dödläge. Slutpunkten slutar svara och får trådansamling. Du får lära dig hur du kan använda olika verktyg för att diagnostisera det här scenariot med flera viktiga delar av diagnostikdata.

I den här självstudien kommer vi att:

  • Undersöka hög CPU-användning
  • Fastställa CPU-användning med dotnet-räknare
  • Använda dotnet-trace för spårningsgenerering
  • Profilprestanda i PerfView
  • Diagnostisera och lösa överdriven CPU-användning

Förutsättningar

Självstudien använder:

CPU-räknare

Innan du försöker samla in diagnostikdata måste du observera ett högt CPU-tillstånd. Kör exempelprogrammet med hjälp av följande kommando från projektrotkatalogen.

dotnet run

Använd följande kommando för att hitta process-ID:t:

dotnet-trace ps

Anteckna process-ID:t från dina kommandoutdata. Vårt process-ID var 22884, men ditt kommer att vara annorlunda. Om du vill kontrollera den aktuella CPU-användningen använder du verktyget dotnet-counters :

dotnet-counters monitor --refresh-interval 1 -p 22884

refresh-interval är antalet sekunder mellan räknarens cpu-värden för avsökning. Resultatet bör likna följande:

Press p to pause, r to resume, q to quit.
    Status: Running

[System.Runtime]
    % Time in GC since last GC (%)                         0
    Allocation Rate / 1 sec (B)                            0
    CPU Usage (%)                                          0
    Exception Count / 1 sec                                0
    GC Heap Size (MB)                                      4
    Gen 0 GC Count / 60 sec                                0
    Gen 0 Size (B)                                         0
    Gen 1 GC Count / 60 sec                                0
    Gen 1 Size (B)                                         0
    Gen 2 GC Count / 60 sec                                0
    Gen 2 Size (B)                                         0
    LOH Size (B)                                           0
    Monitor Lock Contention Count / 1 sec                  0
    Number of Active Timers                                1
    Number of Assemblies Loaded                          140
    ThreadPool Completed Work Item Count / 1 sec           3
    ThreadPool Queue Length                                0
    ThreadPool Thread Count                                7
    Working Set (MB)                                      63

När webbappen körs, direkt efter start, förbrukas inte processorn alls och rapporteras på 0%. Navigera till api/diagscenario/highcpu vägen med 60000 som vägparameter:

https://localhost:5001/api/diagscenario/highcpu/60000

Kör nu kommandot dotnet-counters igen. Om du är intresserad av att bara övervaka räknaren cpu-usage lägger du till "--counters System.Runtime[cpu-usage]" i föregående kommando. Vi är osäkra på om processorn förbrukas, så vi övervakar samma lista över räknare som ovan för att kontrollera att räknarvärdena ligger inom det förväntade intervallet för vårt program.

dotnet-counters monitor -p 22884 --refresh-interval 1

Du bör se en ökning av CPU-användningen enligt nedan (beroende på värddatorn kan du förvänta dig varierande CPU-användning):

Press p to pause, r to resume, q to quit.
    Status: Running

[System.Runtime]
    % Time in GC since last GC (%)                         0
    Allocation Rate / 1 sec (B)                            0
    CPU Usage (%)                                         25
    Exception Count / 1 sec                                0
    GC Heap Size (MB)                                      4
    Gen 0 GC Count / 60 sec                                0
    Gen 0 Size (B)                                         0
    Gen 1 GC Count / 60 sec                                0
    Gen 1 Size (B)                                         0
    Gen 2 GC Count / 60 sec                                0
    Gen 2 Size (B)                                         0
    LOH Size (B)                                           0
    Monitor Lock Contention Count / 1 sec                  0
    Number of Active Timers                                1
    Number of Assemblies Loaded                          140
    ThreadPool Completed Work Item Count / 1 sec           3
    ThreadPool Queue Length                                0
    ThreadPool Thread Count                                7
    Working Set (MB)                                      63

Under hela begärans varaktighet hovra cpu-användningen runt den ökade procentandelen.

Dricks

Om du vill visualisera en ännu högre CPU-användning kan du använda den här slutpunkten på flera webbläsarflikar samtidigt.

I det här läget kan du på ett säkert sätt säga att processorn körs högre än förväntat. Att identifiera effekterna av ett problem är nyckeln till att hitta orsaken. Vi använder effekten av hög CPU-förbrukning utöver diagnostikverktyg för att hitta orsaken till problemet.

Analysera hög CPU med Profiler

När du analyserar en app med hög CPU-användning behöver du ett diagnostikverktyg som kan ge insikter om vad koden gör. Det vanliga valet är en profilerare, och det finns olika profilerare alternativ att välja mellan. dotnet-trace kan användas på alla operativsystem, men dess begränsningar av safe-point bias och managed-only callstacks resulterar i mer allmän information jämfört med en kernelmedveten profilerare som "perf" för Linux eller ETW för Windows. Om din prestandaundersökning endast omfattar hanterad kod räcker det vanligtvis dotnet-trace .

Verktyget perf kan användas för att generera .NET Core-appprofiler. Vi kommer att demonstrera det här verktyget, även om dotnet-trace också kan användas. Avsluta den tidigare instansen av exempelfelsökningsmålet.

DOTNET_PerfMapEnabled Ange miljövariabeln så att .NET-appen skapar en map fil i /tmp katalogen. Den här map filen används av perf för att mappa CPU-adresser till JIT-genererade funktioner efter namn. Mer information finns i Exportera perf-kartor och jit-dumpar.

Kommentar

.NET 6 standardiserar på prefixet DOTNET_ i stället COMPlus_ för för miljövariabler som konfigurerar .NET-körningsbeteende. Prefixet COMPlus_ fortsätter dock att fungera. Om du använder en tidigare version av .NET-körningen bör du fortfarande använda prefixet COMPlus_ för miljövariabler.

Kör exempelfelsökningsmålet i samma terminalsession.

export DOTNET_PerfMapEnabled=1
dotnet run

Träna den höga CPU API-slutpunkten (https://localhost:5001/api/diagscenario/highcpu/60000) igen. När den körs inom en minuts begäran kör perf du kommandot med ditt process-ID:

sudo perf record -p 2266 -g

Kommandot perf startar processen för prestandainsamling. Låt den köras i cirka 20–30 sekunder och tryck sedan på Ctrl+C för att avsluta insamlingsprocessen. Du kan använda samma perf kommando för att se utdata från spårningen.

sudo perf report -f

Du kan också generera en flame-graph med hjälp av följande kommandon:

git clone --depth=1 https://github.com/BrendanGregg/FlameGraph
sudo perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flamegraph.svg

Det här kommandot genererar en flamegraph.svg som du kan visa i webbläsaren för att undersöka prestandaproblemet:

Flame graph SVG image

Analysera hög CPU-data med Visual Studio

Alla *.nettrace-filer kan analyseras i Visual Studio. Om du vill analysera en Linux *.nettrace-fil i Visual Studio överför du filen *.nettrace, förutom de andra nödvändiga dokumenten, till en Windows-dator och öppnar sedan filen *.nettrace i Visual Studio. Mer information finns i Analysera CPU-användningsdata.

Se även

Nästa steg