Condividi tramite


Raccogliere informazioni dettagliate sul caricamento di assembly

A partire da .NET 5, il runtime può generare eventi tramite EventPipe con informazioni dettagliate sul caricamento di assembly gestiti per facilitare la diagnosi dei problemi di caricamento degli assembly. Questi eventi vengono generati dal Microsoft-Windows-DotNETRuntime provider sotto la AssemblyLoader parola chiave (0x4).

Prerequisiti

Annotazioni

L'ambito delle capacità di dotnet-trace va oltre la semplice raccolta di informazioni dettagliate sul caricamento di assembly. Per altre informazioni sull'utilizzo di dotnet-trace, vedere dotnet-trace.

Raccogliere una traccia con eventi di caricamento di assembly

È possibile usare dotnet-trace per tracciare un processo esistente o per avviare un processo figlio e tracciarlo dall'avvio.

Tracciare un processo esistente

Per abilitare gli eventi di caricamento degli assembly nel runtime e raccoglierne una traccia, usare dotnet-trace con il comando seguente:

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

Questo comando raccoglie una traccia del <pid> specificato, abilitando gli eventi AssemblyLoader nel provider Microsoft-Windows-DotNETRuntime. Il risultato è un .nettrace file.

Usare dotnet-trace per avviare un processo figlio e tracciarlo dall'avvio

A volte può essere utile raccogliere una traccia di un processo dall'avvio. Per le app che eseguono .NET 5 o versioni successive, è possibile usare dotnet-trace per eseguire questa operazione.

Il comando seguente avvia hello.exe con arg1 e arg2 come argomenti della riga di comando e raccoglie una traccia dall'avvio del runtime:

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

È possibile interrompere la raccolta della traccia premendo INVIO o CTRL + C. Questo chiude anche hello.exe.

Annotazioni

  • L'avvio hello.exe tramite dotnet-trace reindirizza l'input e l'output e non sarà possibile interagire con esso nella console per impostazione predefinita. Usare l'opzione --show-child-io per interagire con il suo stdin e stdout.
  • Uscendo dallo strumento tramite CTRL+C si termina in modo sicuro sia lo strumento che il processo figlio.
  • Se il processo figlio viene chiuso prima dello strumento, lo strumento viene chiuso e la traccia deve essere visualizzabile in modo sicuro.

Visualizzare una traccia

Il file di traccia raccolto può essere visualizzato in Windows usando la visualizzazione Eventi in PerfView. Tutti gli eventi di caricamento dell'assembly saranno preceduti da Microsoft-Windows-DotNETRuntime/AssemblyLoader.

Esempio (in Windows)

In questo esempio viene usato l'esempio di punti di estensione per il caricamento dell'assembly. L'applicazione tenta di caricare un assembly MyLibrary - un assembly a cui l'applicazione non fa riferimento e che quindi richiede una gestione in un punto di estensione per il caricamento dell'assembly affinché sia caricato con successo.

Raccogliere la traccia

  1. Navigare nella directory con il campione scaricato. Compilare l'applicazione con:

    dotnet build
    
  2. Avviare l'applicazione con argomenti che indicano che deve essere sospesa, in attesa della pressione di un tasto. Al termine della ripresa, tenterà di caricare l'assembly nell'impostazione predefinita AssemblyLoadContext , senza la gestione necessaria per un caricamento riuscito. Passare alla directory di output ed eseguire:

    AssemblyLoading.exe /d default
    
  3. Trova l'ID del processo dell'applicazione.

    dotnet-trace ps
    

    L'elenco mostrerà i processi disponibili. Per esempio:

    35832 AssemblyLoading C:\src\AssemblyLoading\bin\Debug\net5.0\AssemblyLoading.exe
    
  4. Collega dotnet-trace all'applicazione in esecuzione.

    dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 --process-id 35832
    
  5. Nella finestra che esegue l'applicazione premere un tasto qualsiasi per consentire al programma di continuare. La traccia verrà interrotta automaticamente una volta che l'applicazione esce.

Visualizzare la traccia

Aprire la traccia raccolta in PerfView e aprire la visualizzazione Eventi. Filtrare l'elenco di eventi in base agli Microsoft-Windows-DotNETRuntime/AssemblyLoader eventi.

Immagine del filtro del caricatore di assembly PerfView

Verranno visualizzati tutti i caricamenti di assembly che si sono verificati nell'applicazione dopo l'inizio del tracciamento. Per esaminare l'operazione di caricamento dell'assembly interessato in questo esempio - MyLibrary, è possibile applicare ulteriori filtri.

Caricamenti di assembly

Filtrare la visualizzazione in base agli Start eventi Stop e Microsoft-Windows-DotNETRuntime/AssemblyLoader usando l'elenco di eventi a sinistra. Aggiungere le colonne AssemblyName, ActivityIDe Success alla vista. Filtrare in base agli eventi contenenti MyLibrary.

Immagine degli eventi PerfView Start e Stop

Nome evento AssemblyName ActivityID Successo
AssemblyLoader/Start MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/
AssemblyLoader/Stop MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/ Falso

Verrà visualizzata una Start/Stop coppia con Success=False sull'evento Stop , che indica che l'operazione di caricamento non è riuscita. Si noti che i due eventi hanno lo stesso ID attività. L'ID attività può essere utilizzato per filtrare tutti gli altri eventi del caricatore di assembly, lasciando solo quelli che corrispondono a questa operazione di caricamento.

Fallimento del tentativo di caricamento

Per una suddivisione più dettagliata dell'operazione di caricamento, filtrare la visualizzazione in base agli ResolutionAttempted eventi in Microsoft-Windows-DotNETRuntime/AssemblyLoader usando l'elenco di eventi a sinistra. Aggiungere le colonne AssemblyName, Stagee Result alla vista. Filtra gli eventi con l'ID attività della coppia Start/Stop.

Immagine degli eventi PerfView ResolutionAttempted

Nome evento AssemblyName Fase Risultato
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

Gli eventi precedenti indicano che il caricatore di assembly ha tentato di risolvere l'assembly cercando nel contesto di carico corrente, eseguendo la logica di probe predefinita per gli assembly delle applicazioni gestite, richiamando i gestori per l'evento AssemblyLoadContext.Resolving e richiamando i gestori per l'evento AppDomain.AssemblyResolve. Per tutte queste fasi, l'assemblaggio non è stato trovato.

Punti di estensione

Per vedere quali punti di estensione sono stati richiamati, filtra la visualizzazione agli elementi AssemblyLoadContextResolvingHandlerInvoked e AppDomainAssemblyResolveHandlerInvoked sotto Microsoft-Windows-DotNETRuntime/AssemblyLoader utilizzando l'elenco degli eventi a sinistra. Aggiungere le colonne AssemblyName e HandlerName alla vista. Filtra gli eventi con l'ID attività della coppia Start/Stop.

Immagine degli eventi del punto di estensione PerfView

Nome evento AssemblyName HandlerName
AssemblyLoader/AssemblyLoadContextResolvingHandlerInvoked MyLibrary, Culture=neutral, PublicKeyToken=null OnAssemblyLoadContextResolving
AssemblyLoader/AppDomainAssemblyResolveHandlerInvoked MyLibrary, Culture=neutral, PublicKeyToken=null OnAppDomainAssemblyResolve

Gli eventi precedenti indicano che è stato richiamato un gestore denominato OnAssemblyLoadContextResolving per l'evento AssemblyLoadContext.Resolving e che è stato richiamato un gestore denominato OnAppDomainAssemblyResolve per l'evento AppDomain.AssemblyResolve .

Raccogliere un'altra traccia

Eseguire l'applicazione con argomenti in modo che il gestore dell'evento AssemblyLoadContext.Resolving caricherà l'assembly MyLibrary.

AssemblyLoading /d default alc-resolving

Raccogliere e aprire un altro .nettrace file usando i passaggi precedenti.

Filtrare nuovamente sugli eventi Start e Stop per MyLibrary. Dovresti vedere una coppia Start/Stop con un'altra Start/Stop in mezzo. L'operazione di caricamento interno rappresenta il carico attivato dal gestore per AssemblyLoadContext.Resolving quando ha chiamato AssemblyLoadContext.LoadFromAssemblyPath. Questa volta, dovresti vedere Success=True sull'evento Stop, indicando che l'operazione di caricamento è riuscita. Il ResultAssemblyPath campo mostra il percorso dell'assembly risultante.

Immagine degli eventi avviati e arrestati con successo in PerfView

Nome evento AssemblyName ActivityID Successo 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/ Vero C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll
AssemblyLoader/Stop MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/ Vero C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll

È quindi possibile esaminare gli ResolutionAttempted eventi con l'ID attività dal carico esterno per determinare il passaggio in cui l'assembly è stato risolto correttamente. Questa volta, gli eventi mostreranno che la AssemblyLoadContextResolvingEvent fase ha avuto esito positivo. Il ResultAssemblyPath campo mostra il percorso dell'assembly risultante.

Immagine degli eventi ResolutionAttempted di PerfView completati con successo

Nome evento AssemblyName Fase Risultato 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

Guardando gli eventi AssemblyLoadContextResolvingHandlerInvoked, si mostrerà che il gestore denominato OnAssemblyLoadContextResolving è stato richiamato. Il ResultAssemblyPath campo mostra il percorso dell'assembly restituito dal gestore.

Immagine degli eventi del punto di estensione con esito positivo per PerfView

Nome evento AssemblyName HandlerName ResultAssemblyPath
AssemblyLoader/AssemblyLoadContextResolvingHandlerInvoked MyLibrary, Culture=neutral, PublicKeyToken=null OnAssemblyLoadContextResolving C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll

Si noti che non esiste più un ResolutionAttempted evento con la AppDomainAssemblyResolveEvent fase o gli AppDomainAssemblyResolveHandlerInvoked eventi, perché l'assembly è stato caricato correttamente prima di raggiungere il passaggio dell'algoritmo di caricamento che genera l'evento AppDomain.AssemblyResolve .

Vedere anche