Uso di simboli in .NET TraceProcessing

TraceProcessor supporta il caricamento di simboli e il recupero di stack da diverse origini dati. L'applicazione console seguente esamina gli esempi di CPU e restituisce la durata stimata di esecuzione di una funzione specifica (in base al campionamento statistico della CPU nella traccia).

using Microsoft.Windows.EventTracing;
using Microsoft.Windows.EventTracing.Cpu;
using Microsoft.Windows.EventTracing.Symbols;
using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        if (args.Length != 3)
        {
            Console.Error.WriteLine("Usage: GetCpuSampleDuration.exe <trace.etl> <imageName> <functionName>");
            return;
        }

        string tracePath = args[0];
        string imageName = args[1];
        string functionName = args[2];
        Dictionary<string, Duration> matchDurationByCommandLine = new Dictionary<string, Duration>();

        using (ITraceProcessor trace = TraceProcessor.Create(tracePath))
        {
            IPendingResult<ISymbolDataSource> pendingSymbolData = trace.UseSymbols();
            IPendingResult<ICpuSampleDataSource> pendingCpuSamplingData = trace.UseCpuSamplingData();

            trace.Process();

            ISymbolDataSource symbolData = pendingSymbolData.Result;
            ICpuSampleDataSource cpuSamplingData = pendingCpuSamplingData.Result;

            symbolData.LoadSymbolsForConsoleAsync(SymCachePath.Automatic, SymbolPath.Automatic).GetAwaiter().GetResult();

            Console.WriteLine();
            IThreadStackPattern pattern = AnalyzerThreadStackPattern.Parse($"{imageName}!{functionName}");

            foreach (ICpuSample sample in cpuSamplingData.Samples)
            {
                if (sample.Stack != null && sample.Stack.Matches(pattern))
                {
                    string commandLine = sample.Process.CommandLine;

                    if (!matchDurationByCommandLine.ContainsKey(commandLine))
                    {
                        matchDurationByCommandLine.Add(commandLine, Duration.Zero);
                    }

                    matchDurationByCommandLine[commandLine] += sample.Weight;
                }
            }

            foreach (string commandLine in matchDurationByCommandLine.Keys)
            {
                Console.WriteLine($"{commandLine}: {matchDurationByCommandLine[commandLine]}");
            }
        }
    }
}

L'esecuzione di questo programma produce un output simile al seguente:

C:\GetCpuSampleDuration\bin\Debug\> GetCpuSampleDuration.exe C:\boot.etl user32.dll LoadImageInternal
0.0% (0 of 1165; 0 loaded)
<snip>
100.0% (1165 of 1165; 791 loaded)
wininit.exe: 15.99 ms
C:\Windows\Explorer.EXE: 5 ms
winlogon.exe: 20.15 ms
"C:\Users\AdminUAC\AppData\Local\Microsoft\OneDrive\OneDrive.exe" /background: 2.09 ms

(I dettagli dell'output variano a seconda della traccia).

Formato dei simboli

Internamente, TraceProcessor usa il formato SymCache, ovvero una cache di alcuni dati archiviati in un PDB. Durante il caricamento dei simboli, TraceProcessor richiede di specificare una posizione da usare per questi file SymCache (un percorso SymCache) e supporta facoltativamente la specifica SymbolPath per accedere ai PDB. Quando viene fornito SymbolPath, TraceProcessor crea file SymCache dai file PDB in base alle esigenze e l'elaborazione successiva degli stessi dati può usare direttamente i file SymCache per ottenere prestazioni migliori.

Passaggi successivi

In questo tutorial si è appreso come caricare i simboli durante l'elaborazione delle tracce.

Il passaggio successivo consiste nell'apprendere come usare lo streaming per accedere ai dati tracciati senza memorizzare nel buffer tutti gli elementi in memoria.