Tracciare le applicazioni .NET con PerfCollect

Questo articolo si applica a: ✔️ .NET Core 2.1 SDK e versioni successive

Quando si verificano problemi di prestazioni in Linux, è possibile raccogliere una traccia con perfcollect per raccogliere informazioni dettagliate su ciò che si è verificato nel computer al momento del problema di prestazioni.

perfcollect è uno script bash che usa Linux Trace Toolkit: next generation (LTTng) per raccogliere gli eventi scritti dal runtime o da qualsiasi EventSource, nonché perf per raccogliere campioni di CPU del processo di destinazione.

Preparare il computer

Seguire questa procedura per preparare il computer per raccogliere una traccia delle prestazioni con perfcollect.

Nota

Se si esegue l'acquisizione dall'interno di un contenitore, il contenitore deve avere le funzionalità appropriate. Le funzionalità minime necessarie sono PERFMON e SYS_PTRACE. Se l'acquisizione ha esito negativo con il set minimo, aggiungere la funzionalità SYS_ADMIN al contenitore. Per altre informazioni sulla traccia delle applicazioni all'interno di contenitori tramite PerfCollect, consultare Raccogliere i dati di diagnostica nei contenitori.

  1. Scaricare perfcollect.

    curl -OL https://aka.ms/perfcollect
    
  2. Rendere eseguibile lo script.

    chmod +x perfcollect
    
  3. Installare i prerequisiti di traccia: si tratta delle librerie di traccia effettive.

    sudo ./perfcollect install
    

    Verranno installati i prerequisiti seguenti nel computer:

    1. perf: sottosistema Eventi prestazioni Linux e applicazione di raccolta/visualizzatore in modalità utente complementare. perf fa parte dell'origine del kernel Linux, ma in genere non è installata per impostazione predefinita.

    2. LTTng: usato per acquisire i dati degli eventi generati in fase di esecuzione da CoreCLR. Questi dati vengono quindi usati per analizzare il comportamento di vari componenti di runtime, ad esempio GC, JIT e pool di thread.

Le versioni recenti di .NET Core e lo strumento perf Linux supportano la risoluzione automatica dei nomi dei metodi per il codice framework.

Per la risoluzione dei nomi dei metodi delle DLL di runtime nativo (ad esempio libcoreclr.so), perfcollect risolverà i simboli quando converte i dati, ma solo se sono presenti i simboli per questi file binari. Per informazioni dettagliate, consultare la sezione Recupero di simboli per il runtime nativo.

Raccogliere una traccia

  1. Sono disponibili due shell, una per il controllo della traccia, denominata [Traccia], e una per l'esecuzione dell'applicazione, denominata [App].

  2. [Traccia] Avviare la raccolta.

    sudo ./perfcollect collect sampleTrace
    

    Output previsto:

    Collection started.  Press CTRL+C to stop.
    
  3. [App] Configurare la shell dell'applicazione con le variabili di ambiente seguenti. Questo consente la configurazione di traccia di CoreCLR.

    export DOTNET_PerfMapEnabled=1
    export DOTNET_EnableEventLog=1
    

    Nota

    Quando si esegue l'app con .NET 7, è anche necessario impostare DOTNET_EnableWriteXorExecute=0 oltre alle variabili di ambiente precedenti. Ad esempio:

    export DOTNET_EnableWriteXorExecute=0
    

    Nota

    .NET 6 standardizza il prefisso DOTNET_ anziché COMPlus_ per le variabili di ambiente che configurano il comportamento di runtime di .NET. Tuttavia, il prefisso COMPlus_ continuerà a funzionare. Se si usa una versione precedente del runtime .NET, è comunque consigliabile usare il prefisso COMPlus_ per le variabili di ambiente.

  4. [App] Eseguire l'app: consentire l'esecuzione fino a quando è necessario per acquisire il problema di prestazioni. La lunghezza esatta può essere il più breve necessario, purché acquisisca sufficientemente l'intervallo di tempo in cui si verifica il problema di prestazioni da analizzare.

    dotnet run
    
  5. [Traccia] Arrestare la raccolta: premere CTRL+C.

    ^C
    ...STOPPED.
    
    Starting post-processing. This may take some time.
    
    Generating native image symbol files
    ...SKIPPED
    Saving native symbols
    ...FINISHED
    Exporting perf.data file
    ...FINISHED
    Compressing trace files
    ...FINISHED
    Cleaning up artifacts
    ...FINISHED
    
    Trace saved to sampleTrace.trace.zip
    

    Il file di traccia compresso è ora archiviato nella directory di lavoro attuale.

Visualizzare una traccia

Sono disponibili diverse opzioni per visualizzare la traccia raccolta. Le tracce sono visualizzate meglio usando PerfView in Windows, ma possono essere visualizzate direttamente in Linux usando lo stesso PerfCollect o TraceCompass.

Usare PerfCollect per visualizzare il file di traccia

È possibile usare perfcollect per visualizzare la traccia raccolta. A tale scopo, eseguire il comando seguente:

./perfcollect view sampleTrace.trace.zip

Per impostazione predefinita, verrà visualizzata la traccia della CPU dell'applicazione usando perf.

Per esaminare gli eventi raccolti tramite LTTng, è possibile passare il flag -viewer lttng per visualizzare i singoli eventi:

./perfcollect view sampleTrace.trace.zip -viewer lttng

Verrà usato il visualizzatore babeltrace per stampare il payload degli eventi:

# [01:02:18.189217659] (+0.020132603) ubuntu-xenial DotNETRuntime:ExceptionThrown_V1: { cpu_id = 0 }, { ExceptionType = "System.Exception", ExceptionMessage = "An exception happened", ExceptionEIP = 139875671834775, ExceptionHRESULT = 2148734208, ExceptionFlags = 16, ClrInstanceID = 0 }
# [01:02:18.189250227] (+0.020165171) ubuntu-xenial DotNETRuntime:ExceptionCatchStart: { cpu_id = 0 }, { EntryEIP = 139873639728404, MethodID = 139873626968120, MethodName = "void [helloworld] helloworld.Program::Main(string[])", ClrInstanceID = 0 }

Usare PerfView per aprire il file di traccia

Per avere una visualizzazione aggregata sia del CPU campione che degli eventi, è possibile usare PerfView in un computer Windows.

  1. Copiare il file ZIP della traccia da Linux in un computer Windows.

  2. Scaricare PerfView da https://aka.ms/perfview.

  3. Eseguire PerfView.exe

    PerfView.exe <path to trace.zip file>
    

PerfView mostrerà l'elenco delle visualizzazioni supportate in base ai dati contenuti nel file di traccia.

  • Per le indagini sulla CPU, scegliere stack di CPU.

  • Per informazioni dettagliate su GC, scegliere GCStats.

  • Per informazioni JIT riguardanti il processo/modulo/metodo, scegliere JITStats.

  • Se non è disponibile una visualizzazione per le informazioni necessarie, è possibile provare a cercare gli eventi nella visualizzazione eventi non elaborati. Scegliere Eventi.

Per ulteriori informazioni su come interpretare le visualizzazioni in PerfView, consultare i collegamenti alla Guida nella visualizzazione stessa o dalla finestra principale in PerfView, scegliere Guida per>gli utenti.

Nota

Gli eventi scritti tramite API System.Diagnostics.Tracing.EventSource (inclusi gli eventi di Framework) non verranno visualizzati con il nome del provider. Vengono invece scritti come eventi EventSourceEvent nel provider Microsoft-Windows-DotNETRuntime e i relativi payload vengono serializzati in formato JSON.

Nota

Se si osservano [unknown] /memfd:doublemapper fotogrammi nei nomi dei metodi e negli stack di chiamate, impostare DOTNET_EnableWriteXorExecute=0 prima di eseguire l'app di cui si esegue la traccia con perfcollect.

Usare TraceCompass per aprire il file di traccia

Eclipse TraceCompass è un'altra opzione che è possibile usare per visualizzare le tracce. TraceCompass funziona anche nei computer Linux, quindi non è necessario spostare la traccia in un computer Windows. Per usare TraceCompass per aprire il file di traccia, è necessario decomprimere il file.

unzip myTrace.trace.zip

perfcollect salverà la traccia LTTng raccolta in un formato di file CTF in una sottodirectory in lttngTrace. In particolare, il file CTF si troverà in una directory simile a lttngTrace/auto-20201025-101230\ust\uid\1000\64-bit\.

È possibile aprire il file di traccia CTF in TraceCompass selezionando File -> Open Trace e selezionando il file metadata.

Per ulteriori dettagli, consultare la TraceCompass documentazione.

Ottenere i simboli per il runtime nativo

Nella maggior parte dei casi si è interessati al proprio codice, che viene risolto daperfcollect per impostazione predefinita. A volte è utile vedere cosa accade all'interno delle DLL .NET (che è l'ultima sezione su), ma a volte ciò che accade nelle DLL di runtime native (in genere libcoreclr.so), è interessante. perfcollect risolverà i simboli per questi quando converte i dati, ma solo se i simboli per queste DLL native sono presenti (e sono accanto alla libreria per cui sono presenti).

Esiste un comando globale denominato dotnet-symbol che esegue questa operazione. Per usare dotnet-symbol per ottenere simboli di runtime nativi:

  1. Installare dotnet-symbol:

    dotnet tool install -g dotnet-symbol
    
  2. Scaricare i simboli. Se la versione installata del runtime di .NET Core è 2.1.0, il comando per eseguire questa operazione è:

    mkdir mySymbols
    dotnet symbol --symbols --output mySymbols  /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.0/lib*.so
    
  3. Copiare i simboli nella posizione corretta.

    sudo cp mySymbols/* /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.0
    

    Se non è possibile eseguire questa operazione perché non si dispone dell'accesso in scrittura alla directory appropriata, è possibile usare perf buildid-cache per aggiungere i simboli.

In seguito, è necessario ottenere i nomi simbolici per le dll native quando si esegue perfcollect.

Raccogliere in un contenitore Docker

Per ulteriori informazioni su come usare perfcollect negli ambienti contenitore, consultare Raccogliere dati diagnostici nei contenitori.

Ulteriori informazioni sulle opzioni di raccolta

È possibile specificare i flag facoltativi seguenti con perfcollect per soddisfare meglio le esigenze di diagnostica.

Raccogliere per una durata specifica

Quando si desidera raccogliere una traccia per una durata specifica, è possibile usare l'opzione -collectsec seguita da un numero che specifica i secondi totali per cui raccogliere una traccia.

Raccogliere tracce threadtime

Specificando -threadtime con perfcollect è possibile raccogliere i dati di utilizzo della CPU per thread. In questo modo è possibile analizzare la posizione in cui ogni thread ha trascorso il tempo di CPU.

Raccogliere tracce per le prestazioni di Garbage Collector e managed memory

Le opzioni seguenti consentono di raccogliere in modo specifico gli eventi GC dal runtime.

  • perfcollect collect -gccollectonly

Raccogliere solo un set minimo di eventi GC Collection. Si tratta del profilo di raccolta di eventi GC minimo dettagliato con l'impatto più basso sulle prestazioni dell'app di destinazione. Questo comando è analogo al comando PerfView.exe /GCCollectOnly collect in PerfView.

  • perfcollect collect -gconly

Raccogliere eventi di raccolta GC più dettagliati con eventi JIT, Loader ed Exception. Questo richiede eventi più dettagliati (ad esempio le informazioni sull'allocazione e le informazioni di join GC) e avrà un impatto maggiore sulle prestazioni dell'app di destinazione rispetto all'opzione -gccollectonly. Questo comando è analogo al comando PerfView.exe /GCOnly collect in PerfView.

  • perfcollect collect -gcwithheap

Raccogliere gli eventi di raccolta GC più dettagliati, tenendo traccia anche della sopravvivenza e dei movimenti dell'heap. In questo modo viene fornita un'analisi approfondita del comportamento GC, anche se comporta un costo elevato delle prestazioni perché ogni GC può richiedere più di due volte più a lungo. È consigliabile comprendere l'implicazione delle prestazioni dell'uso di questa opzione di traccia quando si esegue la traccia negli ambienti di produzione.