Recopilación de información detallada de carga de ensamblados
A partir de .NET 5, el entorno de ejecución puede emitir eventos a través de EventPipe
con información detallada sobre la carga de ensamblados administrados como ayuda para diagnosticar problemas en la carga de ensamblados. El proveedor Microsoft-Windows-DotNETRuntime
emite estos eventos bajo la palabra clave AssemblyLoader
(0x4
).
Requisitos previos
- SDK de .NET 5 o versiones posteriores
- Herramienta
dotnet-trace
Nota:
El ámbito de las funcionalidades de dotnet-trace
es mayor que la recopilación de información detallada de carga de ensamblados. Para más información sobre el uso de dotnet-trace
, consulte dotnet-trace
.
Recopilación de un seguimiento con eventos de carga de ensamblados
Puede usar dotnet-trace
para hacer un seguimiento de un proceso existente o para iniciar un proceso secundario y hacer un seguimiento desde el inicio.
Seguimiento de un proceso existente
Para habilitar los eventos de carga de ensamblados en el entorno de ejecución y recopilar un seguimiento de ellos, use dotnet-trace
con el siguiente comando:
dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 --process-id <pid>
Este comando recopila un seguimiento del <pid>
especificado, lo que habilita los eventos AssemblyLoader
en el proveedor Microsoft-Windows-DotNETRuntime
. El resultado es un archivo .nettrace
.
Uso de dotnet-trace para iniciar un proceso secundario y hacer un seguimiento desde el inicio
A veces puede resultar útil recopilar un seguimiento de un proceso desde su inicio. Para las aplicaciones que ejecutan .NET 5 o versiones posteriores, puede usar dotnet-trace
para esto.
El comando siguiente inicia hello.exe con arg1
y arg2
como argumentos de la línea de comandos, y recopila un seguimiento de su inicio en tiempo de ejecución:
dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 -- hello.exe arg1 arg2
Para detener la recopilación del seguimiento, presione ENTRAR o CTRL + C. Esto también cierra hello.exe.
Nota
- El inicio de hello.exe mediante
dotnet-trace
redirige su entrada y salida, y usted no podrá interactuar con el archivo en la consola de manera predeterminada. Use el modificador--show-child-io
para interactuar con sustdin
ystdout
. - La salida de la herramienta por medio de CTRL+C o
SIGTERM
finaliza de manera segura la herramienta y el proceso secundario. - Si el proceso secundario termina antes que la herramienta, la herramienta también se cierra y el seguimiento se debería poder ver de forma segura.
Visualización de un seguimiento
El archivo de seguimiento recopilado se puede ver en Windows mediante la vista Eventos en PerfView. Todos los eventos de carga de ensamblados tendrán como prefijo Microsoft-Windows-DotNETRuntime/AssemblyLoader
.
Ejemplo (en Windows)
En este ejemplo se usa el ejemplo de puntos de extensión de la carga de ensamblados. La aplicación intenta cargar un ensamblado MyLibrary
; un ensamblado al que no hace referencia la aplicación y, por tanto, requiere el control en un punto de extensión de carga de ensamblados para que se cargue correctamente.
Recopilación del seguimiento
Navegue hasta el directorio con el ejemplo descargado. Compile la aplicación:
dotnet build
Inicie la aplicación con argumentos que indiquen que debe hacer una pausa, a la espera de que se presione una tecla. Al reanudar la operación, intentará cargar el ensamblado en el
AssemblyLoadContext
predeterminado, sin el control necesario para una carga correcta. Navegue hasta el directorio de salida y ejecute:AssemblyLoading.exe /d default
Busque el identificador de proceso de la aplicación.
dotnet-trace ps
En la salida se enumerarán los procesos disponibles. Por ejemplo:
35832 AssemblyLoading C:\src\AssemblyLoading\bin\Debug\net5.0\AssemblyLoading.exe
Adjunte
dotnet-trace
a la aplicación en ejecución.dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 --process-id 35832
En la ventana que ejecuta la aplicación, presione cualquier tecla para dejar que el programa continúe. El seguimiento se detendrá automáticamente una vez que se cierre la aplicación.
Visualización del seguimiento
Abra el seguimiento recopilado en PerfView y abra la vista Eventos. Filtre la lista de eventos para eventos Microsoft-Windows-DotNETRuntime/AssemblyLoader
.
Se mostrarán todas las cargas de ensamblado que se produjeron en la aplicación después del inicio del seguimiento. Para inspeccionar la operación de carga para el ensamblado de interés para este ejemplo (MyLibrary
), podemos seguir filtrando.
Cargas de ensamblado
Filtre la vista por los eventos Start
y Stop
en Microsoft-Windows-DotNETRuntime/AssemblyLoader
con la lista de eventos de la izquierda. Agregue las columnas AssemblyName
, ActivityID
y Success
a la vista. Filtre los eventos que contienen MyLibrary
.
Nombre del evento | AssemblyName | Identificador de actividad | Correcto |
---|---|---|---|
AssemblyLoader/Start |
MyLibrary, Culture=neutral, PublicKeyToken=null |
//1/2/ | |
AssemblyLoader/Stop |
MyLibrary, Culture=neutral, PublicKeyToken=null |
//1/2/ | False |
Debería ver un par Start
/Stop
con Success=False
en el evento Stop
, lo cual indica que se ha producido un error en la operación de carga. Tenga en cuenta que los dos eventos tienen el mismo identificador de actividad. El identificador de actividad se puede usar para filtrar todos los demás eventos del cargador de ensamblados a solo los que corresponden a esta operación de carga.
Desglose del intento de carga
Para obtener un desglose más detallado de la operación de carga, filtre la vista por los eventos ResolutionAttempted
bajo Microsoft-Windows-DotNETRuntime/AssemblyLoader
mediante la lista de eventos de la izquierda. Agregue las columnas AssemblyName
, Stage
y Result
a la vista. Filtre los eventos con el identificador de actividad del par Start
/Stop
.
Nombre del evento | AssemblyName | Fase | Resultado |
---|---|---|---|
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 |
Los eventos anteriores indican que el cargador de ensamblados intentó resolver el ensamblado examinando el contexto de carga actual, ejecutando la lógica de sondeo predeterminada para los ensamblados de aplicación administrados, invocando controladores para el evento AssemblyLoadContext.Resolving e invocando controladores para AppDomain.AssemblyResolve. En todos estos pasos, no se encontró el ensamblado.
Puntos de extensión
Para ver los puntos de extensión que se invocaron, filtre la vista a AssemblyLoadContextResolvingHandlerInvoked
y AppDomainAssemblyResolveHandlerInvoked
en Microsoft-Windows-DotNETRuntime/AssemblyLoader
mediante la lista de eventos de la izquierda. Agregue las columnas AssemblyName
y HandlerName
a la vista. Filtre los eventos con el identificador de actividad del par Start
/Stop
.
Nombre del evento | AssemblyName | HandlerName |
---|---|---|
AssemblyLoader/AssemblyLoadContextResolvingHandlerInvoked |
MyLibrary, Culture=neutral, PublicKeyToken=null |
OnAssemblyLoadContextResolving |
AssemblyLoader/AppDomainAssemblyResolveHandlerInvoked |
MyLibrary, Culture=neutral, PublicKeyToken=null |
OnAppDomainAssemblyResolve |
Los eventos anteriores indican que se invocó un controlador con el nombre OnAssemblyLoadContextResolving
para el evento AssemblyLoadContext.Resolving y que se invocó un controlador denominado OnAppDomainAssemblyResolve
para el evento AppDomain.AssemblyResolve.
Recopilación de otro seguimiento
Ejecute la aplicación con argumentos de modo que su controlador para el evento AssemblyLoadContext.Resolving cargue el ensamblado MyLibrary
.
AssemblyLoading /d default alc-resolving
Recopile y abra otro archivo .nettrace
con los pasos anteriores.
Filtre de nuevo a los eventos Start
y Stop
de MyLibrary
. Debería ver un par Start
/Stop
con otro Start
/Stop
entre ellos. La operación de carga interna representa la carga desencadenada por el controlador para AssemblyLoadContext.Resolving cuando llamó a AssemblyLoadContext.LoadFromAssemblyPath. Esta vez, debería ver Success=True
en el evento Stop
, lo cual indica que la operación de carga se realizó correctamente. En el campo ResultAssemblyPath
se muestra la ruta de acceso del ensamblado resultante.
Nombre del evento | AssemblyName | Identificador de actividad | Correcto | 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/ | True | C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll |
AssemblyLoader/Stop |
MyLibrary, Culture=neutral, PublicKeyToken=null |
//1/2/ | True | C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll |
A continuación, podemos examinar los eventos ResolutionAttempted
con el identificador de actividad de la carga externa para determinar el paso en el que el ensamblado se resolvió correctamente. Esta vez, los eventos mostrarán que la fase AssemblyLoadContextResolvingEvent
se ha realizado correctamente. En el campo ResultAssemblyPath
se muestra la ruta de acceso del ensamblado resultante.
Nombre del evento | AssemblyName | Fase | Resultado | 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 |
Al fijarse en los eventos AssemblyLoadContextResolvingHandlerInvoked
, verá que se invocó el controlador denominado OnAssemblyLoadContextResolving
. El campo ResultAssemblyPath
muestra la ruta de acceso del ensamblado devuelto por el controlador.
Nombre del evento | AssemblyName | HandlerName | ResultAssemblyPath |
---|---|---|---|
AssemblyLoader/AssemblyLoadContextResolvingHandlerInvoked |
MyLibrary, Culture=neutral, PublicKeyToken=null |
OnAssemblyLoadContextResolving |
C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll |
Tenga en cuenta que ya no hay un evento ResolutionAttempted
con la fase AppDomainAssemblyResolveEvent
ni eventos AppDomainAssemblyResolveHandlerInvoked
, ya que el ensamblado se cargó correctamente antes de alcanzar el paso del algoritmo de carga que genera el evento AppDomain.AssemblyResolve.