Отладка высокой загрузки ЦП в .NET Core

Эта статья относится к: ✔️ пакету SDK для .NET Core 3.1 и более поздних версий

В этом руководстве описано, как выполнить отладку в случае чрезмерной загрузки ЦП. Используя предоставленный пример веб-приложения ASP.NET Core в репозитории исходного кода, можно намеренно вызвать взаимоблокировку. Конечная точка перестанет отвечать, и в ней будут накапливаться потоки. Вы узнаете, как использовать различные средства для диагностики проблемы в этом сценарии на основе ряда ключевых диагностических данных.

При работе с этим руководством вы сделаете следующее:

  • Выяснение причины высокой загрузки ЦП
  • Определение загрузки ЦП с помощью dotnet-counters
  • Использование dotnet-trace для создания трассировки
  • Профилирование производительности в PerfView
  • Диагностика и устранение причины чрезмерной загрузки ЦП

Необходимые компоненты

В руководстве используются следующие ресурсы:

Счетчики ЦП

Прежде чем начать сбор диагностических данных, необходимо воспроизвести условие высокой загрузки ЦП. Запустите пример приложения из корневого каталога примера с помощью следующей команды:

dotnet run

Чтобы узнать ИД процесса, выполните следующую команду:

dotnet-trace ps

Запишите ИД процесса, отображаемый в выходных данных команды. Наш ИД процесса — 22884, но ваш будет другим. Чтобы проверить текущую загрузку ЦП, выполните команду dotnet-counters:

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

refresh-interval — это время в секундах между опросами счетчиком значений ЦП. Результат выполнения должен быть аналогичен следующему:

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

Сразу же после запуска веб-приложения ЦП совсем не используется и его загрузка отображается как равная 0%. Перейдите по маршруту api/diagscenario/highcpu, используя 60000 в качестве параметра маршрута:

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

Теперь выполните команду dotnet-counters повторно. Если вы хотите отслеживать только счетчик cpu-usage , добавьте "-counters System.Runtime[использование ЦП]" в предыдущую команду. Мы не уверены, используется ли ЦП, поэтому мы будем отслеживать тот же список счетчиков, что и выше, чтобы убедиться, что значения счетчиков находятся в ожидаемом диапазоне для нашего приложения.

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

Вы должны увидеть увеличение использования ЦП, как показано ниже (в зависимости от хост-компьютера, ожидается изменение использования ЦП):

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

На протяжении всего запроса использование ЦП будет наведено на увеличение процента.

Совет

Чтобы визуализировать еще более высокий уровень загрузки ЦП, можно запустить эту конечную точку на нескольких вкладках браузера одновременно.

На этом этапе можно с уверенностью сказать, что ЦП работает с большей загрузкой, чем ожидается. Определение последствий проблемы является ключом для поиска причины. Мы будем использовать эффект высокого потребления ЦП в дополнение к средствам диагностики, чтобы найти причину проблемы.

Анализ высокого ЦП с помощью Профилировщика

При анализе приложения с высоким уровнем использования ЦП требуется средство диагностика, которое может предоставить аналитические сведения о том, что делает код. Стандартным инструментом является профилировщик, и вы можете выбрать различные параметры профилировщика. dotnet-trace можно использовать во всех операционных системах, однако его ограничения с предвзятостью безопасной точки и управляемыми вызовами приводят к более общей информации по сравнению с профилировщиком, поддерживающего ядро, например perf для Linux или ETW для Windows. Если исследование производительности включает только управляемый код, обычно dotnet-trace будет достаточно.

Средство perf можно использовать для создания профилей приложений .NET Core. Мы продемонстрируем это средство, хотя также можно использовать dotnet-trace. Выйдите из предыдущего примера целевого объекта отладки.

DOTNET_PerfMapEnabled Задайте переменную среды, чтобы приложение .NET создавало map файл в каталоге/tmp. Этот map файл используется perf для сопоставления адресов ЦП с функциями, созданными JIT по имени. Дополнительные сведения см. в разделе "Экспорт карт perf" и "Дампы jit".

Примечание.

.NET 6 стандартизует префикс DOTNET_ вместо COMPlus_ для переменных среды, которые настраивают поведение .NET во время выполнения. Но префикс COMPlus_ будет и дальше работать. Если вы используете предыдущую версию среды выполнения .NET, следует и дальше использовать префикс COMPlus_ для переменных среды.

Запустите пример целевого объекта отладки в том же сеансе терминала.

export DOTNET_PerfMapEnabled=1
dotnet run

Повторно запустите конечную точку API (https://localhost:5001/api/diagscenario/highcpu/60000) с высокой загрузкой ЦП. Пока она выполняется в рамках 1-минутного запроса, запустите команду perf с ИД процесса:

sudo perf record -p 2266 -g

Команда perf активирует процесс сбора данных производительности. Пусть она выполняется в течение примерно 20–30 секунд. Затем нажмите сочетание клавиш CTRL+C, чтобы выйти из процесса сбора. Для просмотра выходных данных трассировки можно использовать ту же команду perf.

sudo perf report -f

Вы также можете создать flame-graph с помощью следующих команд:

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

Эта команда создает файл flamegraph.svg, который можно просмотреть в браузере для изучения проблемы с производительностью.

Flame graph SVG image

Анализ данных с высоким уровнем ЦП с помощью Visual Studio

Все файлы *.nettrace можно анализировать в Visual Studio. Чтобы проанализировать файл Linux *.nettrace в Visual Studio, передайте файл *.nettrace, помимо других необходимых документов, на компьютер Windows, а затем откройте файл *.nettrace в Visual Studio. Дополнительные сведения см. в разделе "Анализ данных об использовании ЦП".

См. также

Следующие шаги