Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Эта статья относится к пакету ✔️ SDK для .NET Core 3.1 и более поздних версий.
В этом руководстве вы узнаете, как отлаживать чрезмерный сценарий использования ЦП. Используя приведенный пример репозитория исходного кода веб-приложения ASP.NET Core, можно намеренно вызвать дедлок. Конечная точка перестанет отвечать на запросы и накапливать потоки. Вы узнаете, как использовать различные средства для диагностики этого сценария с помощью нескольких ключевых элементов диагностических данных.
При работе с этим руководством вы сделаете следующее:
- Изучение высокого использования ЦП
- Определение использования ЦП с помощью dotnet-counters
- Использование dotnet-trace для создания трассировки
- Производительность профиля в PerfView
- Диагностика и устранение чрезмерного использования ЦП
Предпосылки
В этом руководстве используется:
- Пакет SDK для .NET Core 3.1 или более поздняя версия.
- Пример целевого объекта отладки для активации сценария.
- dotnet-trace для перечисления процессов и создания профиля.
- dotnet-counters для мониторинга использования ЦП.
Счетчики ЦП
Прежде чем пытаться выполнить эту инструкцию, установите последнюю версию dotnet-counters:
dotnet tool install --global dotnet-counters
Если приложение работает с версией .NET старше, чем .NET 9, интерфейс вывода dotnet-counters будет выглядеть несколько иначе. Подробнее см. в документации dotnet-counters.
Прежде чем пытаться собирать диагностические данные, необходимо наблюдать за высоким состоянием ЦП. Запустите пример приложения с помощью следующей команды из корневого каталога проекта.
dotnet run
Чтобы проверить текущее использование ЦП, используйте команду dotnet-counters :
dotnet-counters monitor -n DiagnosticScenarios --showDeltas
Выходные данные должны быть похожи на следующие:
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
Рассматривая значения Last Deltadotnet.process.cpu.time, можно определить, сколько секунд в период обновления (который в настоящее время по умолчанию составляет 1 с) процессор был активен. При запуске веб-приложения сразу после запуска ЦП не используется вообще, и эти разностные значения являются обоими 0. Перейдите к маршруту api/diagscenario/highcpu с 60000 параметром маршрута:
https://localhost:5001/api/diagscenario/highcpu/60000
Теперь повторно выполните команду dotnet-counters .
dotnet-counters monitor -n DiagnosticScenarios --showDeltas
Вы должны увидеть увеличение использования ЦП, как показано ниже (в зависимости от хост-компьютера, ожидается изменение использования ЦП):
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
На протяжении всего времени выполнения запроса, использование ЦП будет оставаться на повышенном уровне.
Подсказка
Чтобы визуализировать еще большее использование ЦП, эту конечную точку можно использовать одновременно на нескольких вкладках браузера.
На этом этапе можно безопасно сказать, что ЦП работает выше, чем ожидалось. Определение последствий проблемы является ключом для поиска причины. Мы будем использовать эффект высокого потребления ЦП в дополнение к средствам диагностики, чтобы найти причину проблемы.
Анализ высокого ЦП с помощью Профилировщика
При анализе приложения с высоким уровнем использования ЦП используйте профилировщик, чтобы понять, что делает код.
dotnet-trace collect работает во всех операционных системах, но смещение безопасных точек и управляемые только стековые вызовы ограничивают его более общими сведениями по сравнению с ядровым профилировщиком, таким как ETW для Windows или perf для Linux. В зависимости от версии вашей операционной системы и .NET на конкретной платформе могут быть доступны улучшенные возможности профилирования — см. вкладки, где содержатся подробные инструкции для каждой платформы.
Используйте dotnet-trace collect-linux (.NET 10+)
Начиная с .NET 10 и более поздних версий, dotnet-trace collect-linux является рекомендуемым подходом к профилированию на Linux. Он объединяет EventPipe с perf_events уровня ОС для создания единой трассировки, которая включает как управляемые, так и собственные вызовы, все без необходимости перезапуска процесса. Для этого требуются корневые разрешения и ядро Linux 6.4+ с CONFIG_USER_EVENTS=y. Прочитайте о collect-linux prerequisites для получения полной информации о требованиях.
Убедитесь, что тестовый отладочный объект настроен для .NET 10 или более поздней версии, затем запустите его и повторно протестируйте конечную точку с высокой загрузкой ЦП (https://localhost:5001/api/diagscenario/highcpu/60000). Поскольку она выполняется в течение запрашиваемой 1 минуты, выполните команду dotnet-trace collect-linux, чтобы записать трассировку на уровне компьютера.
sudo dotnet-trace collect-linux
Дайте ему проработать около 20–30 секунд, затем нажмите Ctrl+C или Enter, чтобы остановить сбор данных. Результатом является файл, включающий как управляемые, так и собственные стеки вызовов .nettrace.
Откройте .nettrace с помощью PerfView и используйте представление CPU стеков, чтобы определить методы, которые потребляют больше всего процессорного времени.
Сведения о разрешении собственных символов среды выполнения в трассировке см. в разделе "Получение символов для собственных кадров среды выполнения".
Используйте perf
Средство perf также можно использовать для создания профилей приложений .NET Core. Выход из предыдущего экземпляра примера целевого объекта отладки.
DOTNET_PerfMapEnabled Задайте переменную среды, чтобы приложение .NET создавало map файл в каталоге/tmp. Этот map файл используется perf для сопоставления адресов процессора с функциями, созданными JIT по имени. Для получения дополнительной информации см. раздел «Экспорт карт perf» и «дампы jit».
Запустите образец целевого объекта отладки в том же сеансе терминала.
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
Вы также можете создать диаграмму пламени с помощью следующих команд:
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