Поделиться через


Сбор подробных сведений о загрузке сборок

Начиная с .NET 5, среда выполнения может выдавать события через EventPipe с подробными сведениями о загрузке управляемых сборок, что помогает в диагностике проблем с их загрузкой. Эти события испускаются поставщиком Microsoft-Windows-DotNETRuntime с помощью ключевого слова AssemblyLoader (0x4).

Предпосылки

Замечание

Область возможностей dotnet-trace охватывает большее, чем просто сбор подробных сведений о загрузке сборок. Дополнительные сведения об использовании dotnet-traceсм. в разделе dotnet-trace.

Соберите трассировку загрузки сборок

Можно использовать dotnet-trace для трассировки существующего процесса или запуска дочернего процесса и его трассировки от запуска.

Прослеживание существующего процесса

Чтобы включить события загрузки сборок в среде выполнения и собрать их трассировку, используйте dotnet-trace следующую команду:

dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 --process-id <pid>

Эта команда собирает трассировку указанного <pid> объекта, активируя события AssemblyLoader в поставщике Microsoft-Windows-DotNETRuntime. Результатом является .nettrace файл.

Использовать dotnet-trace для запуска дочернего процесса и его трассировки с момента запуска

Иногда бывает полезно собрать трассировку процесса с момента его запуска. Для приложений, работающих под управлением .NET 5 или более поздней версии, вы можете использовать dotnet-trace, чтобы сделать это.

Следующая команда запускает hello.exe с аргументами командной строки arg1, а arg2 собирает трассировку при запуске среды выполнения.

dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 -- hello.exe arg1 arg2

Можно остановить сбор трассировки, нажав клавишу Enter или Ctrl + C. Это также закрывает hello.exe.

Замечание

  • Запуск hello.exe с помощью dotnet-trace перенаправляет свои входные и выходные данные, поэтому по умолчанию вы не сможете взаимодействовать с ним на консоли. Используйте переключатель --show-child-io для взаимодействия с stdin и stdout.
  • Выход из программы при помощи CTRL+C или SIGTERM безопасно завершает как программу, так и дочерний процесс.
  • Если дочерний процесс завершает работу до утилиты, утилита также завершает работу, и трассировку можно безопасно просмотреть.

Просмотр трассировки

Собранный файл трассировки можно просмотреть в Windows с помощью представления событий в PerfView. Все события загрузки сборки будут префиксированы Microsoft-Windows-DotNETRuntime/AssemblyLoader.

Пример (в Windows)

В этом примере используется пример точек расширения загрузки сборки. Приложение пытается загрузить сборку MyLibrary — сборку, на которую не ссылается приложение, и поэтому требуется обработка в точке расширения загрузки сборки для успешной загрузки.

Соберите трассировку

  1. Перейдите к каталогу с скачанным примером. Создайте приложение с помощью следующих приложений:

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

    AssemblyLoading.exe /d default
    
  3. Найдите идентификатор процесса приложения.

    dotnet-trace ps
    

    Выходные данные будут перечислять доступные процессы. Рассмотрим пример.

    35832 AssemblyLoading C:\src\AssemblyLoading\bin\Debug\net5.0\AssemblyLoading.exe
    
  4. Присоедините dotnet-trace к работающему приложению.

    dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 --process-id 35832
    
  5. В окне, на котором запущено приложение, нажмите любой ключ, чтобы разрешить программе продолжить. Трассировка будет автоматически останавливаться после выхода приложения.

Просмотр трассировки

Откройте собранную трассировку в PerfView и откройте представление "События". Фильтрация списка событий по событиям Microsoft-Windows-DotNETRuntime/AssemblyLoader .

Образ фильтра загрузчика сборок PerfView

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

Загрузка сборок

Отфильтруйте представление на события Start и Stop под Microsoft-Windows-DotNETRuntime/AssemblyLoader, используя список событий слева. Добавьте столбцы AssemblyNameи ActivityIDSuccess в представление. Фильтровать события, содержащие MyLibrary.

Изображение событий запуска и остановки PerfView

Имя события Имя сборки Идентификатор Активности Успех
AssemblyLoader/Start MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/
AssemblyLoader/Stop MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/ Неправда

Вы увидите одну Start/Stop пару с Success=False событием, указывающую на сбой Stop операции загрузки. Обратите внимание, что два события имеют одинаковый идентификатор действия. Идентификатор действия можно использовать для фильтрации всех других событий загрузчика сборок только тем, которые соответствуют этой операции загрузки.

Разбивка попытки загрузки

Для более подробной детализации операции загрузки фильтруйте представление по ResolutionAttempted событиям под Microsoft-Windows-DotNETRuntime/AssemblyLoader используя список событий слева. Добавьте столбцы AssemblyNameи StageResult в представление. Фильтруйте события с идентификатором действия из пары Start/Stop.

Изображение событий ResolutionAttempted в PerfView

Имя события Имя сборки Этап Результат
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null FindInLoadContext AssemblyNotFound
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null ApplicationAssemblies AssemblyNotFound
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null AssemblyLoadContextResolvingEvent AssemblyNotFound
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null AppDomainAssemblyResolveEvent AssemblyNotFound

Приведенные выше события указывают на то, что загрузчик сборок попытался разрешить сборку, обращаясь к текущему контексту загрузки, выполняя логику проверки по умолчанию для сборок управляемых приложений, вызывая обработчики события AssemblyLoadContext.Resolving и вызывая обработчики для события AppDomain.AssemblyResolve. Для всех этих шагов сборка не была обнаружена.

Точки расширения

Чтобы увидеть, какие точки расширения были вызваны, отфильтруйте представление до AssemblyLoadContextResolvingHandlerInvoked и AppDomainAssemblyResolveHandlerInvoked, находясь под Microsoft-Windows-DotNETRuntime/AssemblyLoader, используя список событий слева. Добавьте столбцы AssemblyName и HandlerName в представление. Фильтруйте события с идентификатором действия из пары Start/Stop.

Изображение событий точек расширения в PerfView

Имя события Имя сборки ИмяОбработчика
AssemblyLoader/AssemblyLoadContextResolvingHandlerInvoked MyLibrary, Culture=neutral, PublicKeyToken=null OnAssemblyLoadContextResolving
AssemblyLoader/AppDomainAssemblyResolveHandlerInvoked MyLibrary, Culture=neutral, PublicKeyToken=null OnAppDomainAssemblyResolve

Приведенные выше события указывают на то, что для OnAssemblyLoadContextResolving события был вызван AssemblyLoadContext.Resolving обработчик, а для OnAppDomainAssemblyResolve события был вызван AppDomain.AssemblyResolve обработчик.

Соберите ещё одну трассировку

Запустите приложение с аргументами, таким образом, что его обработчик события AssemblyLoadContext.Resolving загрузит сборку MyLibrary .

AssemblyLoading /d default alc-resolving

Соберите и откройте другой файл, выполнив указанные .nettraceвыше действия.

Фильтруйте снова по Start и Stop событиям для MyLibrary. Вы должны увидеть комбинацию Start/Stop с ещё одной комбинацией Start/Stop между ними. Внутренняя операция загрузки представляет собой процесс загрузки, вызванный обработчиком для AssemblyLoadContext.Resolving, когда он вызвал AssemblyLoadContext.LoadFromAssemblyPath. На этот раз вы должны увидеть Success=True на событии Stop, что указывает на успешное выполнение операции загрузки. В ResultAssemblyPath поле показан путь к результирующей сборке.

Успешное изображение событий начала и остановки PerfView

Имя события Имя сборки Идентификатор Активности Успех ResultAssemblyPath
AssemblyLoader/Start MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/
AssemblyLoader/Start MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null //1/2/1/
AssemblyLoader/Stop MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null //1/2/1/ Верно C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll
AssemblyLoader/Stop MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/ Верно C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll

Затем можно просмотреть ResolutionAttempted события с ID активности из внешней загрузки, чтобы определить шаг, на котором сборка была успешно выполнена. На этот раз события покажут, что AssemblyLoadContextResolvingEvent этап был успешным. В ResultAssemblyPath поле показан путь к результирующей сборке.

Изображение событий PerfView ResolutionAttempted успешно

Имя события Имя сборки Этап Результат ResultAssemblyPath
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null FindInLoadContext AssemblyNotFound
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null ApplicationAssemblies AssemblyNotFound
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null AssemblyLoadContextResolvingEvent Success C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll

Изучение AssemblyLoadContextResolvingHandlerInvoked событий покажет, что обработчик OnAssemblyLoadContextResolving был вызван. В ResultAssemblyPath поле показан путь к сборке, возвращаемой обработчиком.

Изображение успешных событий точки расширения в PerfView

Имя события Имя сборки ИмяОбработчика ResultAssemblyPath
AssemblyLoader/AssemblyLoadContextResolvingHandlerInvoked MyLibrary, Culture=neutral, PublicKeyToken=null OnAssemblyLoadContextResolving C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll

Обратите внимание, что больше не происходит событие ResolutionAttempted с этапом AppDomainAssemblyResolveEvent, а также любые события AppDomainAssemblyResolveHandlerInvoked, поскольку сборка была успешно загружена до того, как алгоритм загрузки достиг шага, вызывающего событие AppDomain.AssemblyResolve.

См. также