Debug penggunaan CPU tinggi di .NET Core

Artikel ini berlaku untuk: ✔️ .NET Core 3.1 SDK dan versi yang lebih baru

Dalam tutorial ini, Anda akan mempelajari cara men-debug skenario penggunaan CPU yang berlebihan. Dengan menggunakan contoh yang disediakan ASP.NET repositori kode sumber aplikasi web Core, Anda dapat menyebabkan kebuntuan dengan sengaja. Titik akhir akan berhenti merespons dan mengalami akumulasi utas. Anda akan mempelajari bagaimana Anda dapat menggunakan berbagai alat untuk mendiagnosis skenario ini dengan beberapa potongan utama data diagnostik.

Dalam tutorial ini, Anda akan:

  • Menyelidiki penggunaan CPU yang tinggi
  • Menentukan penggunaan CPU dengan penghitung dotnet
  • Menggunakan dotnet-trace untuk pembuatan jejak
  • Performa profil di PerfView
  • Mendiagnosis dan memecahkan penggunaan CPU yang berlebihan

Prasyarat

Tutorial ini menggunakan:

Penghitung CPU

Sebelum mencoba mengumpulkan data diagnostik, Anda perlu mengamati kondisi CPU yang tinggi. Jalankan aplikasi sampel menggunakan perintah berikut dari direktori akar proyek.

dotnet run

Untuk menemukan ID proses, gunakan perintah berikut:

dotnet-trace ps

Catat ID proses dari output perintah Anda. ID proses kami adalah 22884, tetapi id Anda akan berbeda. Untuk memeriksa penggunaan CPU saat ini, gunakan perintah alat penghitung dotnet :

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

refresh-interval adalah jumlah detik antara nilai CPU polling penghitung. Output harus sama dengan berikut ini.

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

Dengan aplikasi web berjalan, segera setelah startup, CPU tidak digunakan sama sekali dan dilaporkan di 0%. Navigasikan api/diagscenario/highcpu ke rute dengan 60000 sebagai parameter rute:

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

Sekarang, jalankan kembali perintah dotnet-counters. Jika tertarik untuk memantau penghitung cpu-usage saja, tambahkan '--counters System.Runtime[cpu-usage]' ke perintah sebelumnya. Kami tidak yakin apakah CPU sedang digunakan, jadi kami akan memantau daftar penghitung yang sama seperti di atas untuk memverifikasi nilai penghitung berada dalam rentang yang diharapkan untuk aplikasi kami.

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

Anda akan melihat peningkatan penggunaan CPU seperti yang ditunjukkan di bawah ini (tergantung pada komputer host, mengharapkan penggunaan CPU yang bervariasi):

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

Selama durasi permintaan, penggunaan CPU akan melayang di sekitar persentase yang meningkat.

Tip

Untuk memvisualisasikan penggunaan CPU yang lebih tinggi, Anda dapat menjalankan titik akhir ini di beberapa tab browser secara bersamaan.

Pada titik ini, Anda dapat dengan aman mengatakan CPU berjalan lebih tinggi dari yang Anda harapkan. Mengidentifikasi efek masalah adalah kunci untuk menemukan penyebabnya. Kami akan menggunakan efek konsumsi CPU yang tinggi selain alat diagnostik untuk menemukan penyebab masalah.

Menganalisis CPU Tinggi dengan Profiler

Saat menganalisis aplikasi dengan penggunaan CPU yang tinggi, Anda memerlukan alat diagnostik yang dapat memberikan wawasan tentang apa yang dilakukan kode. Pilihan yang biasa adalah profiler, dan ada opsi profiler yang berbeda untuk dipilih. dotnet-trace dapat digunakan pada semua sistem operasi, namun, keterbatasan bias titik aman dan tumpukan panggilan khusus terkelola menghasilkan informasi yang lebih umum dibandingkan dengan profiler yang sadar kernel seperti 'perf' untuk Linux atau ETW untuk Windows. Jika penyelidikan performa Anda hanya melibatkan kode terkelola, umumnya dotnet-trace akan cukup.

Alat perf ini dapat digunakan untuk menghasilkan profil aplikasi .NET Core. Kami akan menunjukkan alat ini, meskipun dotnet-trace juga dapat digunakan. Keluar dari instans sebelumnya dari target debug sampel.

Atur DOTNET_PerfMapEnabled variabel lingkungan untuk menyebabkan aplikasi .NET membuat file map di direktori /tmp. File map ini digunakan oleh perf untuk memetakan alamat CPU ke fungsi yang dihasilkan JIT berdasarkan nama. Untuk informasi selengkapnya, lihat Mengekspor peta perf dan jit dump.

Catatan

.NET 6 menstandarkan pada prefiks DOTNET_ daripada COMPlus_ untuk variabel lingkungan yang mengonfigurasi perilaku run-time .NET. Namun, prefiks COMPlus_ akan terus berfungsi. Jika Anda menggunakan versi runtime .NET sebelumnya, Anda masih harus menggunakan prefiks COMPlus_ untuk variabel lingkungan.

Jalankan target debug sampel dalam sesi terminal yang sama.

export DOTNET_PerfMapEnabled=1
dotnet run

Jalankan titik akhir API CPU tinggi (https://localhost:5001/api/diagscenario/highcpu/60000) lagi. Saat berjalan dalam permintaan 1 menit, jalankan perintah perf dengan ID proses Anda:

sudo perf record -p 2266 -g

Perintah perf memulai proses pengumpulan performa. Biarkan berjalan selama sekitar 20-30 detik, lalu tekan Ctrl+C untuk keluar dari proses pengumpulan. Anda dapat menggunakan perintah perf yang sama untuk melihat output pelacakan.

sudo perf report -f

Anda juga dapat membuat grafik api dengan menggunakan perintah berikut:

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

Perintah ini menghasilkan flamegraph.svg yang dapat Anda lihat di browser untuk menyelidiki masalah performa:

Flame graph SVG image

Menganalisis Data CPU Tinggi dengan Visual Studio

Semua file *.nettrace dapat dianalisis di Visual Studio. Untuk menganalisis file Linux *.nettrace di Visual Studio, transfer file *.nettrace, selain dokumen lain yang diperlukan, ke komputer Windows, lalu buka file *.nettrace di Visual Studio. Untuk informasi selengkapnya, lihat Menganalisis Data Penggunaan CPU.

Baca juga

Langkah berikutnya