Отладка высокой загрузки ЦП в .NET Core
Эта статья относится к: ✔️ пакету SDK для .NET Core 3.1 и более поздних версий
В этом руководстве описано, как выполнить отладку в случае чрезмерной загрузки ЦП. Используя предоставленный пример веб-приложения ASP.NET Core в репозитории исходного кода, можно намеренно вызвать взаимоблокировку. Конечная точка перестанет отвечать, и в ней будут накапливаться потоки. Вы узнаете, как использовать различные средства для диагностики проблемы в этом сценарии на основе ряда ключевых диагностических данных.
При работе с этим руководством вы сделаете следующее:
- Выяснение причины высокой загрузки ЦП
- Определение загрузки ЦП с помощью dotnet-counters
- Использование dotnet-trace для создания трассировки
- Профилирование производительности в PerfView
- Диагностика и устранение причины чрезмерной загрузки ЦП
Необходимые компоненты
В руководстве используются следующие ресурсы:
- Пакет SDK для .NET Core 3.1 или более поздней версии.
- Пример целевого объекта отладки для активации сценария.
- dotnet-trace для вывода списка процессов и создания профиля.
- dotnet-counters для мониторинга загрузки ЦП.
Счетчики ЦП
Прежде чем начать сбор диагностических данных, необходимо воспроизвести условие высокой загрузки ЦП. Запустите пример приложения из корневого каталога примера с помощью следующей команды:
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
, который можно просмотреть в браузере для изучения проблемы с производительностью.
Анализ данных с высоким уровнем ЦП с помощью Visual Studio
Все файлы *.nettrace можно анализировать в Visual Studio. Чтобы проанализировать файл Linux *.nettrace в Visual Studio, передайте файл *.nettrace, помимо других необходимых документов, на компьютер Windows, а затем откройте файл *.nettrace в Visual Studio. Дополнительные сведения см. в разделе "Анализ данных об использовании ЦП".
См. также
- dotnet-trace для отображения списка процессов
- dotnet-counters для проверки использования управляемой памяти
- dotnet-dump для сбора и анализа файла дампа
- dotnet/diagnostics