Бөлісу құралы:


Программа для сбора и анализа дампов (dotnet-dump)

Эта статья относится к: ✔️ dotnet-dump версии 3.0.47001 и более поздних версий.

Примечание.

dotnet-dump для macOS поддерживается только с .NET 5 и более поздних версий.

Установка

Есть два способа загрузки и установки dotnet-dump:

  • Глобальный инструмент dotnet:

    Чтобы установить последнюю версию пакета dotnet-dumpNuGet, используйте команду dotnet tool install.

    dotnet tool install --global dotnet-dump
    
  • Прямое скачивание:

    скачайте исполняемый файл средства, соответствующий вашей платформе:

    ОС Платформа
    Windows x86 | x64 | Руку | Arm-x64
    Линукс x64 | Руку | Arm64 | musl-x64 | musl-Arm64

Примечание.

Для использования dotnet-dump в приложении x86 необходима соответствующая версия средства для архитектуры x86.

Краткие сведения

dotnet-dump [-h|--help] [--version] <command>

Описание

Глобальное средство dotnet-dump — это способ сбора и анализа дампов на Windows, Linux и macOS без использования собственного отладчика. Это средство имеет важное значение на таких платформах, как Alpine Linux, где отсутствует полноценно работающее средство lldb. Средство dotnet-dump позволяет выполнять команды SOS для анализа сбоев и сборщика мусора (GC), но не поддерживает некоторые функции, как, например, отображение собственных кадров стека, потому что не является встроенным отладчиком.

Параметры

  • --version

    Отображение версии служебной программы dotnet-dump.

  • -h|--help

    Отображение справки в командной строке.

Команды

Команда
сбор dotnet-dump
Анализ dotnet-dump
dotnet-dump ps

сбор dotnet-dump

Записывает дамп из процесса.

Краткие сведения

dotnet-dump collect [-h|--help] [-p|--process-id] [-n|--name] [--type] [-o|--output] [--diag] [--crashreport]

Параметры

  • -h|--help

    Отображение справки в командной строке.

  • -p|--process-id <PID>

    Указывает идентификатор процесса, из которого нужно собрать дамп.

  • -n|--name <name>

    Имя процесса, из которого нужно получить дамп.

  • --type <Full|Heap|Mini>

    Указывает тип дампа, который определяет типы собираемых из процесса данных. Существует три типа:

    • Full — самый крупный дамп, содержащий всю память, включая образы модулей.
    • Heap — большой и сравнительно подробный дамп, который содержит списки модулей, списки потоков, все стеки, сведения об исключениях, сведения об обработке и всю память, за исключением сопоставленных образов.
    • Mini — небольшой дамп, который содержит списки модулей, списки потоков, сведения об исключениях и все стеки.
    • Triage — небольшой дамп, содержащий списки модулей, списки потоков, сведения об исключениях, все стеки и удаленные личные данные.

    Если тип не указан, по умолчанию используется вариант Full.

  • -o|--output <output_dump_path>

    Полный путь и имя файла, в который будет записан собранный дамп. Убедитесь, что пользователь, в котором выполняется процесс dotnet, имеет разрешения на запись в указанный каталог.

    Если значение не указано, используются следующие:

    • По умолчанию .\dump_YYYYMMDD_HHMMSS.dmp на Windows.
    • По умолчанию используется ./core_YYYYMMDD_HHMMSS в Linux и macOS.

    YYYYMMDD обозначает формат "год/месяц/день", а HHMMSS — формат "час/минута/секунда".

  • --diag

    Включает ведение журнала диагностики для сбора дампов.

  • --crashreport

    Включает создание отчета о сбоях.

Примечание.

В Linux и macOS эта команда ожидает, что целевое приложение и dotnet-dump будут совместно использовать одну и ту же переменную среды TMPDIR. В противном случае время ожидания команды истечет.

Примечание.

Чтобы собрать дамп с помощью dotnet-dump, ее необходимо запустить от имени пользователя, запустившего целевой процесс, или от имени привилегированного пользователя. В противном случае средство не сможет установить соединение с целевым процессом.

Примечание.

Сбор полного дампа или дампа кучи может привести к тому, что ОПЕРАЦИОННая система будет выполнять страницу в значительной виртуальной памяти для целевого процесса. Если целевой процесс выполняется в контейнере с принудительным ограничением памяти, увеличение использования памяти может привести к прекращению работы контейнера в случае превышения предела. Мы рекомендуем протестировать, чтобы убедиться, что ограничение памяти установлено достаточно высоким. Другой вариант — временно изменить или удалить ограничение до сбора дампа, если ваша среда поддерживает это.

Анализ dotnet-dump

Запускает интерактивную оболочку для просмотра дампа. Эта оболочка принимает различные команды SOS.

Краткие сведения

dotnet-dump analyze <dump_path> [-h|--help] [-c|--command]

Аргументы

  • <dump_path>

    Указывает путь к анализируемому файлу дампа.

Параметры

  • -c|--command <debug_command>

    Выполняет команду при запуске. Несколько экземпляров этого параметра можно использовать в вызове к командам цепочки. Команды будут выполняться в том порядке, в который они указаны в командной строке. Если вы хотите, чтобы dotnet dump выйти после выполнения команд, последняя команда должна быть "exit".

Анализ команд SOS

Команда Функция
analyzeoom Отображает сведения о последнем объекте OOM, возникшем в запросе на выделение кучи GC.
clrmodules Перечисляет управляемые модули в процессе.
clrstack Обеспечивает трассировку стека только для управляемого кода.
clrthreads Перечисляет управляемые потоки, которые выполняются.
clru Отображение дизассемблированного кода с аннотациями для управляемого метода.
d или readmemory Дамп содержимого памяти.
dbgout Включает и отключает (-off) внутреннее ведение журнала SOS.
dso Отображает все управляемые объекты, обнаруженные в пределах границ текущего стека.
dumpalc Отображает сведения о коллекционируемом assemblyLoadContext, в который загружается указанный объект.
dumparray Отображает сведения об управляемом массиве.
dumpasync Отображение сведений об асинхронных конечных автоматах для кучи со сборкой мусора.
dumpassembly Отображение сведений о сборке.
dumpclass Отображает сведения о структуре EEClass по указанному адресу.
dumpconcurrentdictionary Отображает параллельное содержимое словаря.
dumpconcurrentqueue Отображает содержимое параллельной очереди.
dumpdelegate Отображение сведений о делегате.
dumpdomain Отображает сведения обо всех сборках в пределах всех доменов приложений или указанных.
dumpgcdata Отображает сведения о данных GC.
dumpgen Отображает содержимое кучи для указанного поколения.
dumpheap Отображение сведений о куче со сборкой мусора и статистики сборки мусора по объектам.
dumpil Отображает общий промежуточный язык (CIL), связанный с управляемым методом.
dumplog Записывает в указанный файл содержимое журнала нагрузок, хранящегося в памяти.
dumpmd Отображает сведения о структуре MethodDesc по указанному адресу.
dumpmodule Отображение сведений о модуле, находящемся по указанному адресу.
dumpmt Отображение сведений о таблице методов, расположенной по указанному адресу.
dumpobj Отображение сведений об объекте, находящемся по указанному адресу.
dumpruntimetypes Находит все объекты System.RuntimeType в куче GC и выводит имя типа и MethodTable, которые они ссылаются.
dumpsig Дамп подписи метода или поля, указанного <sigaddr> <moduleaddr>.
dumpsigelem Дамп одного элемента объекта сигнатуры.
dumpstackobjects Отображает все управляемые объекты, обнаруженные в пределах границ текущего стека.
dumpvc Отображает сведения о полях класса значений.
eeheap Отображение сведений о памяти процессов, занятой внутренними структурами данных среды выполнения.
eestack Выполняет dumpstack во всех потоках процесса.
eeversion Отображает сведения о версиях среды выполнения и SOS.
ehinfo Отображает блоки обработки исключений в методе JIT-ed.
exit или quit Выход из интерактивного режима.
finalizequeue Отображает все объекты, зарегистрированные для заключительной обработки.
findappdomain Пытается устранить домен приложения объекта GC.
gchandles Отображает статистику дескрипторов сборщика мусора в составе процесса.
gcheapstat Отображает статистику о сборщике мусора.
gcinfo Отображает кодировку JIT GC для метода.
gcroot Отображение сведений о ссылках (или корневых элементах) объекта, который расположен по указанному адресу.
gcwhere Отображает расположение в куче GC указанного адреса.
histclear Освобождение всех ресурсов, используемых семейством команд Hist.
histinit Инициализирует структуры SOS из журнала нагрузки, сохраненного в отлаживаемом объекте.
histobj Проверяет все записи журнала перемещения нагрузки и отображает цепочку перемещений сборки мусора, которые могли привести к адресу, переданному в качестве аргумента.
histobjfind Отображение всех записей журнала, ссылающихся на объект по указанному адресу.
histroot Отображает сведения о повышениях и перемещениях указанного корневого элемента.
histstats Отображает статистику журнала стресса.
ip2md Отображает структуру MethodDesc по указанному адресу в коде после его JIT-компиляции.
listnearobj Отображает предыдущий объект и успешное выполнение указанного адреса.
logopen Включает ведение журнала файлов консоли.
logclose Отключает ведение журнала файлов консоли.
logging Включает или отключает внутреннее ведение журнала SOS.
lm или modules Отображение выполняемых собственных модулей.
name2ee Отображает структуры MethodTable и EEClass для указанного типа или метода в указанном модуле.
objsize Отображает размер указанного объекта.
parallelstacks Отображает стек объединенных потоков аналогично панели Visual Studio "Параллельные стеки".
pathto Отображает путь к GC от <root> до <target>.
pe или printexception Отображает и форматирует поля всех производных объектов класса Exception, находящегося по указанному адресу.
r или registers Отображает регистры потока.
runtimes Выводит список сред выполнения в целевом объекте или изменяет среду выполнения по умолчанию.
setclrpath Задает путь для загрузки файлов dac/dbi coreclr с помощью setclrpath <path>.
setsymbolserver Включение поддержки сервера символов.
sos Выполняет различные команды отладки coreclr. Используйте синтаксис sos <command-name> <args>. Дополнительные сведения можно получить с помощью команды soshelp.
soshelp или help Отображает все доступные команды.
soshelp <command> или help <command> Отображение сведений об указанной команде.
syncblk Отображение сведений о заполнителе SyncBlock.
taskstate Отображает состояние задачи в удобочитаемом формате.
threadpool Отображает сведения о пуле потоков среды выполнения.
threadpoolqueue Отображает рабочие элементы пула потоков очереди.
threadstate Довольно печатает значение состояния потоков.
threads <threadid> или setthread <threadid> Отображение или изменение идентификатора текущего потока для команд SOS.
timerinfo Отображает сведения о выполнении таймеров.
token2ee Отображает структуру MethodTable и структуру MethodDesc для указанного токена и модуля.
traverseheap Записывает данные кучи в файл в формате, понятном профилировщиком СРЕДЫ CLR.
verifyheap Проверяет кучу GC на наличие признаков повреждения.
verifyobj Проверяет объект, передаваемый в качестве аргумента, на наличие повреждений.

Примечание.

Дополнительные сведения можно найти в расширении отладки SOS для .NET.

dotnet-dump ps

Выводит список процессов dotnet, из которыми можно собирать дампы. dotnet-dump версии 6.0.320703 и более поздние также отображают аргументы командной строки, с которыми был запущен каждый процесс, если они доступны.

Краткие сведения

dotnet-dump ps [-h|--help]

Пример

Предположим, что вы запускаете длинное приложение с помощью команды dotnet run --configuration Release. В другом окне выполните dotnet-dump ps команду. Выходные данные, которые вы увидите, приведены ниже. Аргументы командной строки, если таковые имеются, отображаются в dotnet-dump версии 6.0.320703 и более поздних версий.

> dotnet-dump ps

  21932 dotnet     C:\Program Files\dotnet\dotnet.exe   run --configuration Release
  36656 dotnet     C:\Program Files\dotnet\dotnet.exe

С использованием dotnet-dump

Первым шагом является сборка дампа. Этот шаг можно пропустить, если уже создан основной дамп. Операционная система или встроенная функция создания dump среды выполнения .NET Core может создавать основные дампы.

$ dotnet-dump collect --process-id 1902
Writing minidump to file ./core_20190226_135837
Written 98983936 bytes (24166 pages) to core file
Complete

Теперь запустите анализ основного дампа с помощью команды analyze:

$ dotnet-dump analyze ./core_20190226_135850
Loading core dump: ./core_20190226_135850
Ready to process analysis commands. Type 'help' to list available commands or 'help [command]' to get detailed help on a command.
Type 'quit' or 'exit' to exit the session.
>

Это действие открывает интерактивный сеанс, который принимает команды следующего вида:

> clrstack
OS Thread Id: 0x573d (0)
    Child SP               IP Call Site
00007FFD28B42C58 00007fb22c1a8ed9 [HelperMethodFrame_PROTECTOBJ: 00007ffd28b42c58] System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean, Boolean)
00007FFD28B42DD0 00007FB1B1334F67 System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo) [/root/coreclr/src/mscorlib/src/System/Reflection/RuntimeMethodInfo.cs @ 472]
00007FFD28B42E20 00007FB1B18D33ED SymbolTestApp.Program.Foo4(System.String) [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 54]
00007FFD28B42ED0 00007FB1B18D2FC4 SymbolTestApp.Program.Foo2(Int32, System.String) [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 29]
00007FFD28B42F00 00007FB1B18D2F5A SymbolTestApp.Program.Foo1(Int32, System.String) [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 24]
00007FFD28B42F30 00007FB1B18D168E SymbolTestApp.Program.Main(System.String[]) [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 19]
00007FFD28B43210 00007fb22aa9cedf [GCFrame: 00007ffd28b43210]
00007FFD28B43610 00007fb22aa9cedf [GCFrame: 00007ffd28b43610]

Чтобы получить сведения о необработанном исключении, которое привело к сбою приложения, выполните:

> pe -lines
Exception object: 00007fb18c038590
Exception type:   System.Reflection.TargetInvocationException
Message:          Exception has been thrown by the target of an invocation.
InnerException:   System.Exception, Use !PrintException 00007FB18C038368 to see more.
StackTrace (generated):
SP               IP               Function
00007FFD28B42DD0 0000000000000000 System.Private.CoreLib.dll!System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean, Boolean)
00007FFD28B42DD0 00007FB1B1334F67 System.Private.CoreLib.dll!System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)+0xa7 [/root/coreclr/src/mscorlib/src/System/Reflection/RuntimeMethodInfo.cs @ 472]
00007FFD28B42E20 00007FB1B18D33ED SymbolTestApp.dll!SymbolTestApp.Program.Foo4(System.String)+0x15d [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 54]
00007FFD28B42ED0 00007FB1B18D2FC4 SymbolTestApp.dll!SymbolTestApp.Program.Foo2(Int32, System.String)+0x34 [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 29]
00007FFD28B42F00 00007FB1B18D2F5A SymbolTestApp.dll!SymbolTestApp.Program.Foo1(Int32, System.String)+0x3a [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 24]
00007FFD28B42F30 00007FB1B18D168E SymbolTestApp.dll!SymbolTestApp.Program.Main(System.String[])+0x6e [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 19]

StackTraceString: <none>
HResult: 80131604

Анализ утечек памяти и выделения

Утечки памяти возникают, когда приложение содержит ссылки на объекты, которые больше не нужны, предотвращая восстановление памяти сборщиком мусора. Используется dotnet-dump для выявления утечек памяти, поиска крупнейших объектов и понимания того, где используется память.

Полное пошаговое руководство по отладке утечки памяти см. в разделе Debug утечка памяти в .NET.

Определение крупнейших объектов

dumpheap Используйте команду с -stat параметром, чтобы просмотреть сводку объектов в куче, отсортированную по общему размеру:

> dumpheap -stat

Statistics:
              MT    Count    TotalSize Class Name
00007f6c1eeefba8      576        59904 System.Reflection.RuntimeMethodInfo
00007f6c1dc021c8     1749        95696 System.SByte[]
00000000008c9db0     3847       116080      Free
00007f6c1e784a18      175       128640 System.Char[]
00007f6c1dbf5510      217       133504 System.Object[]
00007f6c1dc014c0      467       416464 System.Byte[]
00007f6c21625038        6      4063376 testwebapi.Controllers.Customer[]
00007f6c20a67498   200000      4800000 testwebapi.Controllers.Customer
00007f6c1dc00f90   206770     19494060 System.String
Total 428516 objects

В этом выходных данных показано, какие типы используют большую память. В этом примере System.String объекты используют около 19 МБ, а Customer объекты потребляют около 4,8 МБ.

Определение объектов по пространству имен или сборке

Чтобы найти, какие модули или пространства имен используют память, используйте -type параметр с частичным именем типа для фильтрации результатов:

> dumpheap -type MyCompany.Data -stat

Statistics:
              MT    Count    TotalSize Class Name
00007f6c21625038    15000      3600000 MyCompany.Data.CustomerRecord
00007f6c21625040     8000      2560000 MyCompany.Data.OrderHistory
00007f6c21625048     2000       960000 MyCompany.Data.ProductCache
Total 25000 objects, 7120000 bytes

Этот подход помогает определить, какие части базы кода отвечают за потребление памяти.

Поиск наибольшего числа экземпляров

Чтобы узнать, какие типы имеют большинство экземпляров независимо от общего размера, просмотрите столбец Count в выходных dumpheap -stat данных. Объекты с высоким числом экземпляров могут указывать на неэффективные проблемы при создании или кэшировании объектов:

> dumpheap -stat

Statistics:
              MT    Count    TotalSize Class Name
00007f6c1dc00f90   206770     19494060 System.String
00007f6c20a67498   200000      4800000 testwebapi.Controllers.Customer
00007f6c1dc021c8     1749        95696 System.SByte[]

В этом примере показаны 206 770 String экземпляров и 200 000 Customer экземпляров.

Анализ ссылок на объекты с помощью gcroot

После идентификации больших или многочисленных объектов используйте gcroot для того, чтобы узнать, почему объект не собирается мусора. Команда gcroot показывает эталонную цепочку из корней GC в определенный объект:

> dumpheap -mt 00007f6c20a67498
         Address               MT     Size
00007f6ad09421f8 00007f6c20a67498       24
...

> gcroot 00007f6ad09421f8

Thread 3f68:
    00007F6795BB58A0 00007F6C1D7D0745 testwebapi.Controllers.CustomerCache.GetAll()
        rbx:  (interior)
            ->  00007F6BDFFFF038 System.Object[]
            ->  00007F69D0033570 testwebapi.Controllers.Processor
            ->  00007F69D0033588 testwebapi.Controllers.CustomerCache
            ->  00007F69D00335A0 System.Collections.Generic.List`1[[testwebapi.Controllers.Customer]]
            ->  00007F6C000148A0 testwebapi.Controllers.Customer[]
            ->  00007F6AD0942258 testwebapi.Controllers.Customer

Found 1 root.

В этом выходных данных показано, что Customer объект хранится CustomerCache объектом, который помогает определить источник утечки в коде.

Анализ памяти по размеру объекта

-min Используйте параметры для -max фильтрации объектов по размеру:

> dumpheap -min 100000 -stat

Statistics:
              MT    Count    TotalSize Class Name
00007f6c21625038        6      4063376 testwebapi.Controllers.Customer[]
00007f6c1dc014c0       12       416464 System.Byte[]
Total 18 objects

Эта команда показывает только объекты размером более 100 000 байт, помогая сосредоточиться на крупнейших потребителей памяти.

Поиск взаимоблокировок

Используется dotnet-dump для диагностики ситуаций взаимоблокировки, когда потоки блокируются в ожидании ресурсов. Полное пошаговое руководство по отладке взаимоблокировки см. в разделе Debug взаимоблокировки в .NET.

Вывод списка всех потоков

threads Используйте команду, чтобы просмотреть все управляемые потоки:

> threads
*0 0x1DBFF (121855)
 1 0x1DC01 (121857)
 2 0x1DC02 (121858)
 ...

Проверка стека потоков

Используйте clrstack -all для просмотра стеков вызовов всех потоков:

> clrstack -all

Найдите шаблоны, в которых несколько потоков блокируются Monitor.Enter или аналогичные примитивы синхронизации.

Поиск владельцев блокировки

syncblk Используйте команду, чтобы узнать, какие потоки удерживают блокировки и какие потоки ожидают:

> syncblk
Index         SyncBlock MonitorHeld Recursion Owning Thread Info          SyncBlock Owner
   43 00000246E51268B8          603         1 0000024B713F4E30 5634  28   00000249654b14c0 System.Object
   44 00000246E5126908            3         1 0000024B713F47E0 51d4  29   00000249654b14d8 System.Object

В столбце MonitorHeld отображается количество потоков, ожидающих блокировки. В столбце "Сведения о потоке владения" показано, какой поток владеет блокировкой.

Сценарии расширенного анализа памяти

Сравнение нескольких дампов

Чтобы понять рост памяти с течением времени, соберите несколько дампов и сравните их:

  1. Сбор базового дампа: dotnet-dump collect -p <pid> -o baseline.dmp
  2. Позвольте приложению запускать и использовать больше памяти.
  3. Сбор второго дампа: dotnet-dump collect -p <pid> -o after.dmp
  4. Анализ дампов и сравнение dumpheap -stat результатов.

Найдите типы, которые имеют значительно больше экземпляров или больше общих размеров во втором дампах.

Анализ памяти для определенных типов объектов

Для дампа всех экземпляров определенного типа:

> dumpheap -type Customer
         Address               MT     Size
00007f6ad09421f8 00007f6c20a67498       24
00007f6ad0942210 00007f6c20a67498       24
...

Затем используйте dumpobj для изучения отдельных объектов:

> dumpobj 00007f6ad09421f8
Name:        testwebapi.Controllers.Customer
MethodTable: 00007f6c20a67498
EEClass:     00007f6c21625000
Size:        24(0x18) bytes
File:        /app/testwebapi.dll
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
00007f6c1dc00f90  4000001        8        System.String  0 instance 00007f6ad09421f0 Name
00007f6c1dbf4c18  4000002       10         System.Int32  1 instance               42 Id

Сбор дампа в контейнере Docker

dotnet-dump требует ptrace возможностей в контейнере. Распространенным способом предоставления их является запуск контейнера с --cap-add=SYS_PTRACE. В зависимости от среды может потребоваться также настроить профиль seccomp контейнера. Ознакомьтесь с дампами: вопросы и ответы по диагностике проблем с конфигурацией безопасности контейнеров.

Чтобы установить dotnet-dump в рабочем образе без пакета SDK .NET, используйте ссылки на скачивание направленные ссылки из раздела установки или используйте сборку Docker multi-stage Docker для копирования двоичных файлов инструментов из образа пакета SDK. Полные рекомендации по диагностике контейнеров см. в разделе "Сбор диагностики в контейнерах Linux".

Устранение неполадок с сбором дампов

Сбор дампов требует, чтобы процесс мог вызываться ptrace. При возникновении проблем с сбором дампов может быть настроена среда, на которой вы работаете, для ограничения таких вызовов. Ознакомьтесь с нашими дампами: часто задаваемые вопросы об устранении неполадок и возможных решениях распространенных проблем.

См. также