Профилирование: dotnet-counters, dotnet-trace, dotnet-dump, PerfView

↑ 7.1 Производительность .NET и кэширование · → Следующая

Желательно~3 мин чтенияУровень: senior

Зачем это на собесе

«Сервис тормозит или течёт память — что делаете?» Ждут метод и инструменты, а не догадки.

Объяснение

Порядок: метрики → гипотеза → профиль → исправление → замер.

ИнструментЧто показывает
dotnet-countersметрики рантайма в реальном времени: CPU, GC, аллокации, ThreadPool, исключения
dotnet-traceтрассировка (CPU sampling, события) → .nettrace, открывается в PerfView/Speedscope/VS
dotnet-dumpснимок памяти: dumpheap -stat, gcroot, clrstack -all
dotnet-gcdumpлёгкий снимок кучи (только графы объектов)
PerfView, Visual Studio Profiler, JetBrains dotTrace/dotMemoryанализ CPU, памяти, аллокаций
Application Insights, OpenTelemetry, Pyroscope/Parcaнепрерывное профилирование в проде
dotnet-counters monitor -n MyService --counters System.Runtime,Microsoft.AspNetCore.Hosting
dotnet-trace collect -p <pid> --profile cpu-sampling --duration 00:00:30
dotnet-dump collect -p <pid> && dotnet-dump analyze core_...
> dumpheap -stat        # кто занимает память
> gcroot <адрес>        # почему объект не освобождается
> clrstack -all         # что делают потоки (deadlock, блокировки)

Типичные диагнозы:

СимптомПричина
Высокий CPU«горячий» метод, регулярные выражения, сериализация, спин
Рост памятиутечка через события/статические кэши/HttpClient, большой LOH
Высокий gen2 GCмного долгоживущих аллокаций, LOH
Низкий CPU, высокая задержкаблокировка потоков, thread starvation, ожидание внешних систем
Рост числа потоковsync-over-async

Нюансы и подводные камни

  • Профилировать нужно на реалистичной нагрузке и в Release-сборке.
  • Дамп содержит данные памяти, включая секреты и персональные данные: храните и передавайте осторожно.
  • В контейнере нужны права и общий /tmp для диагностического сокета.
  • Не оптимизируйте без измерения: узкое место часто не там, где кажется.

Практика

  1. Воспроизведите утечку статическим списком и найдите её через dumpheap/gcroot.
  2. Снимите CPU-трассу и найдите самый дорогой метод.
  3. Наблюдайте в dotnet-counters рост ThreadPool при sync-over-async.

Вопросы с ответами

Связанные темы