Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Ten artykuł dotyczy: ✔️ .NET Core 3.1 SDK i nowszych wersji
Z tego samouczka dowiesz się, jak debugować nadmierny scenariusz użycia procesora CPU. Korzystając z podanego przykładu repozytorium kodu źródłowego ASP.NET Core aplikacji internetowej, możesz celowo spowodować zakleszczenie. Punkt końcowy przestanie odpowiadać i wystąpi nagromadzenie wątków. Dowiesz się, jak można używać różnych narzędzi do diagnozowania tego scenariusza z kilkoma kluczowymi elementami danych diagnostycznych.
Ten samouczek obejmuje następujące kroki:
- Badanie wysokiego użycia CPU
- Określanie użycia procesora CPU za pomocą dotnet-counters
- Użyj dotnet-trace do generowania śladów
- Wydajność profilu w programie PerfView
- Diagnozowanie i rozwiązywanie nadmiernego użycia procesora
Wymagania wstępne
Samouczek wykorzystuje:
- Pakiet .NET Core 3.1 SDK lub nowsza wersja.
- Przykładowy element docelowy debugowania w celu wyzwolenia scenariusza.
- dotnet-trace do wyświetlania listy procesów i generowania profilu.
- dotnet-counters do monitorowania użycia CPU.
Liczniki procesora CPU
Przed podjęciem próby przeprowadzenia tego samouczka zainstaluj najnowszą wersję liczników dotnet::
dotnet tool install --global dotnet-counters
Jeśli aplikacja korzysta z wersji platformy .NET starszej niż .NET 9, wyjściowy interfejs użytkownika liczników dotnet-counter będzie wyglądać nieco inaczej; Aby uzyskać szczegółowe informacje, zobacz dotnet-counters .
Przed podjęciem próby zebrania danych diagnostycznych należy obserwować wysokie użycie CPU. Uruchom przykładową aplikację przy użyciu następującego polecenia z katalogu głównego projektu.
dotnet run
Aby sprawdzić bieżące użycie procesora CPU, użyj polecenia narzędzia dotnet-counters :
dotnet-counters monitor -n DiagnosticScenarios --showDeltas
Dane wyjściowe powinny być podobne do następujących:
Press p to pause, r to resume, q to quit.
Status: Running
Name Current Value Last Delta
[System.Runtime]
dotnet.assembly.count ({assembly}) 111 0
dotnet.gc.collections ({collection})
gc.heap.generation
------------------
gen0 8 0
gen1 1 0
gen2 0 0
dotnet.gc.heap.total_allocated (By) 4,042,656 24,512
dotnet.gc.last_collection.heap.fragmentation.size (By)
gc.heap.generation
------------------
gen0 801,728 0
gen1 6,048 0
gen2 0 0
loh 0 0
poh 0 0
dotnet.gc.last_collection.heap.size (By)
gc.heap.generation
------------------
gen0 811,512 0
gen1 562,024 0
gen2 1,095,056 0
loh 98,384 0
poh 24,528 0
dotnet.gc.last_collection.memory.committed_size (By) 5,623,808 0
dotnet.gc.pause.time (s) 0.019 0
dotnet.jit.compilation.time (s) 0.582 0
dotnet.jit.compiled_il.size (By) 138,895 0
dotnet.jit.compiled_methods ({method}) 1,470 0
dotnet.monitor.lock_contentions ({contention}) 4 0
dotnet.process.cpu.count ({cpu}) 22 0
dotnet.process.cpu.time (s)
cpu.mode
--------
system 0.109 0
user 0.453 0
dotnet.process.memory.working_set (By) 65,515,520 0
dotnet.thread_pool.queue.length ({work_item}) 0 0
dotnet.thread_pool.thread.count ({thread}) 0 0
dotnet.thread_pool.work_item.count ({work_item}) 6 0
dotnet.timer.count ({timer}) 0 0
Skupienie się na wartościach Last Delta informuje nas, ile sekund w okresie odświeżania (obecnie ustawionym na wartość domyślną 1 s) procesor był aktywny. Po uruchomieniu aplikacji internetowej natychmiast po starcie procesor nie jest używany w ogóle, a te delty są zarówno 0. Przejdź do ścieżki api/diagscenario/highcpu z 60000 jako parametrem ścieżki.
https://localhost:5001/api/diagscenario/highcpu/60000
Teraz uruchom ponownie polecenie dotnet-counters .
dotnet-counters monitor -n DiagnosticScenarios --showDeltas
Powinien zostać wyświetlony wzrost użycia procesora, co pokazano poniżej (zależnie od maszyny hosta, oczekuj różnego użycia procesora):
Press p to pause, r to resume, q to quit.
Status: Running
Name Current Value Last Delta
[System.Runtime]
dotnet.assembly.count ({assembly}) 111 0
dotnet.gc.collections ({collection})
gc.heap.generation
------------------
gen0 8 0
gen1 1 0
gen2 0 0
dotnet.gc.heap.total_allocated (By) 4,042,656 24,512
dotnet.gc.last_collection.heap.fragmentation.size (By)
gc.heap.generation
------------------
gen0 801,728 0
gen1 6,048 0
gen2 0 0
loh 0 0
poh 0 0
dotnet.gc.last_collection.heap.size (By)
gc.heap.generation
------------------
gen0 811,512 0
gen1 562,024 0
gen2 1,095,056 0
loh 98,384 0
poh 24,528 0
dotnet.gc.last_collection.memory.committed_size (By) 5,623,808 0
dotnet.gc.pause.time (s) 0.019 0
dotnet.jit.compilation.time (s) 0.582 0
dotnet.jit.compiled_il.size (By) 138,895 0
dotnet.jit.compiled_methods ({method}) 1,470 0
dotnet.monitor.lock_contentions ({contention}) 4 0
dotnet.process.cpu.count ({cpu}) 22 0
dotnet.process.cpu.time (s)
cpu.mode
--------
system 0.344 0.013
user 14.203 0.963
dotnet.process.memory.working_set (By) 65,515,520 0
dotnet.thread_pool.queue.length ({work_item}) 0 0
dotnet.thread_pool.thread.count ({thread}) 0 0
dotnet.thread_pool.work_item.count ({work_item}) 6 0
dotnet.timer.count ({timer}) 0 0
przez cały czas trwania żądania użycie procesora będzie oscylować wokół zwiększonej wartości.
Wskazówka
Aby zwizualizować jeszcze wyższe użycie procesora CPU, możesz wykonać ten punkt końcowy na wielu kartach przeglądarki jednocześnie.
W tym momencie można stwierdzić, że procesor działa na wyższych obrotach niż się spodziewano. Identyfikowanie skutków problemu jest kluczem do znalezienia przyczyny. Oprócz narzędzi diagnostycznych użyjemy efektu wysokiego użycia procesora CPU, aby znaleźć przyczynę problemu.
Analizowanie wysokiego użycia CPU za pomocą profilera
Podczas analizowania aplikacji z wysokim użyciem procesora CPU użyj profilera, aby zrozumieć, co robi kod.
dotnet-trace collect działa na wszystkich systemach operacyjnych, ale stronnicze punkty kontrolne i tylko zarządzane stosy wywołań ograniczają je do bardziej ogólnych informacji niż profiler obsługujący jądro, taki jak ETW dla systemu Windows lub perf dla systemu Linux. W zależności od systemu operacyjnego i wersji platformy .NET mogą być dostępne ulepszone możliwości profilowania — zapoznaj się z kartami specyficznymi dla platformy, aby uzyskać szczegółowe wskazówki.
Użyj dotnet-trace collect-linux (.NET 10+)
W programie .NET 10 lub nowszym dotnet-trace collect-linux zalecane jest podejście profilowania w systemie Linux. Łączy EventPipe z perf_events na poziomie systemu operacyjnego, aby utworzyć jedną spójną trasę, która obejmuje zarówno zarządzane, jak i natywne stosy wywołań, bez konieczności ponownego uruchamiania procesu. Wymaga to uprawnień głównych i jądra systemu Linux w wersji 6.4 lub nowszej z programem CONFIG_USER_EVENTS=y. Zobacz wymagania wstępne collect-linux dla pełnych wymagań.
Upewnij się, że przykładowy cel debugowania został skonfigurowany do docelowego środowiska .NET 10 lub nowszego, a następnie uruchom go i ponownie przećwicz punkt końcowy obciążający procesor (https://localhost:5001/api/diagscenario/highcpu/60000). Gdy jest ono uruchamiane w ciągu 1-minutowego żądania, uruchom polecenie dotnet-trace collect-linux , aby przechwycić ślad obejmujący całą maszynę:
sudo dotnet-trace collect-linux
Poczekaj około 20–30 sekund, a następnie naciśnij klawisze Ctrl+C lub Enter , aby zatrzymać kolekcję. Wynikiem jest .nettrace plik zawierający zarówno zarządzane, jak i natywne stosy wywołań.
Otwórz element .nettrace za pomocą PerfView i użyj widoku Stosy CPU aby zidentyfikować metody zużywające najwięcej czasu CPU.
Aby uzyskać informacje na temat rozpoznawania natywnych symboli środowiska uruchomieniowego w śladzie, zobacz Pobieranie symboli dla natywnych ramek środowiska uruchomieniowego.
Użyj perf
Narzędzie perf może również służyć do generowania profilów aplikacji platformy .NET Core. Zamknij poprzednie wystąpienie przykładowego celu debugowania.
Ustaw zmienną DOTNET_PerfMapEnabled środowiskową, aby spowodować utworzenie pliku w map katalogu przez aplikację /tmp .NET. Ten map plik jest używany przez perf do mapowania adresów CPU na funkcje generowane przez JIT według nazwy. Aby uzyskać więcej informacji, sprawdź Eksportowanie map wydajności i zrzutów JIT.
Uruchom przykładowy element docelowy debugowania w tej samej sesji terminalu.
export DOTNET_PerfMapEnabled=1
dotnet run
Ponownie przetestować punkt końcowy API obciążającego procesor (https://localhost:5001/api/diagscenario/highcpu/60000). Podczas wykonywania żądania o czasie trwania jednej minuty, uruchom polecenie perf z użyciem identyfikatora procesu:
sudo perf record -p 2266 -g
Polecenie perf uruchamia proces zbierania wydajności. Poczekaj około 20–30 sekund, a następnie naciśnij Ctrl+C , aby zakończyć proces zbierania. Możesz użyć tego samego polecenia perf, aby wyświetlić wynik śladu.
sudo perf report -f
Możesz również wygenerować graf płomienia przy użyciu następujących poleceń:
git clone --depth=1 https://github.com/BrendanGregg/FlameGraph
sudo perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flamegraph.svg
To polecenie generuje element flamegraph.svg , który można wyświetlić w przeglądarce w celu zbadania problemu z wydajnością:
Analizowanie danych wysokiego użycia procesora CPU za pomocą programu Visual Studio
Wszystkie pliki *.nettrace można analizować w programie Visual Studio. Aby przeanalizować plik *.nettrace systemu Linux w programie Visual Studio, przenieś plik *.nettrace, oprócz innych niezbędnych dokumentów, na maszynę z systemem Windows, a następnie otwórz plik *.nettrace w programie Visual Studio. Aby uzyskać więcej informacji, zobacz Analizowanie danych użycia procesora CPU.
Zobacz także
- dotnet-trace aby wyświetlić listę procesów
- dotnet-counters służy do sprawdzania użycia pamięci zarządzanej
- dotnet-dump do zbierania i analizowania pliku zrzutu
- dotnet/diagnostics