static void Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("Specify the name of one trace to be summarized.");
                return;
            }

            var traceName = args[0];

            if (!File.Exists(traceName))
            {
                Console.Error.WriteLine("File '{0}' does not exist.", traceName);
                return;
            }

            var settings = new TraceProcessorSettings
            {
                // Don't print a setup message on first run.
                SuppressFirstTimeSetupMessage = true
            };

            using (ITraceProcessor trace = TraceProcessor.Create(traceName, settings))
            {
                // Get process details, including command lines.
                var pendingProcessData = trace.UseProcesses();
                // Get CPU performance counters, on every context switch.
                var pendingCounterData = trace.UseProcessorCounters();

                trace.Process();

                var processData = pendingProcessData.Result;
                var counterData = pendingCounterData.Result;

                var countersByProcess = FindInterestingProcesses(processData);

                // Accumulate data for all of the interesting processes.
                foreach (var entry in counterData.ContextSwitchCounterDeltas)
                {
                    // This sometimes happens - handle it.
                    if (entry.Process == null)
                    {
                        continue;
                    }

                    Counters last;
                    if (!countersByProcess.TryGetValue(entry.Process, out last))
                    {
                        continue;
                    }

                    // Accumulate counter values and execution time.
                    foreach (var key in entry.RawCounterDeltas.Keys)
                    {
                        last.counters.TryGetValue(key, out ulong lastCount);
                        lastCount         += entry.RawCounterDeltas[key];
                        last.counters[key] = lastCount;
                    }
                    last.runTime_ns      += (entry.StopTime - entry.StartTime).Nanoseconds;
                    last.contextSwitches += 1;

                    countersByProcess[entry.Process] = last;
                }

                // Sort the data by CPU time and print it.
                var sortedCounterData = new List <KeyValuePair <IProcess, Counters> >(countersByProcess);
                sortedCounterData.Sort((x, y) => y.Value.runTime_ns.CompareTo(x.Value.runTime_ns));

                bool printHeader = true;
                foreach (var entry in sortedCounterData)
                {
                    if (printHeader)
                    {
                        Console.Write("{0,-29} - CPU time (s) - context switches", "Image name");
                        foreach (var counterName in entry.Value.counters.Keys)
                        {
                            int fieldWidth = Math.Max(13, counterName.Length);
                            Console.Write(", {0}", counterName.PadLeft(fieldWidth));
                        }
                        Console.WriteLine();
                        printHeader = false;
                    }

                    // Arbitrary cutoff for what is "interesting"
                    if (entry.Value.runTime_ns < 100 * 1000 * 1000)
                    {
                        continue;
                    }

                    Console.Write("{0,-29} -     {1,8:0.00} - {2,16}", entry.Value.description,
                                  entry.Value.runTime_ns / 1e9, entry.Value.contextSwitches);
                    foreach (var counterName in entry.Value.counters.Keys)
                    {
                        int fieldWidth = Math.Max(13, counterName.Length);
                        Console.Write(", {0}",
                                      entry.Value.counters[counterName].ToString().PadLeft(fieldWidth));
                    }
                    Console.WriteLine();
                }
            }
        }
Exemple #2
0
    public static int Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.Error.WriteLine("Usage: CyclesPerInstruction.exe <trace.etl>");
            return(1);
        }

        string tracePath = args[0];

        TraceProcessorSettings settings = new TraceProcessorSettings {
            AllowLostEvents = true
        };

        using (ITraceProcessor trace = TraceProcessor.Create(tracePath, settings))
        {
            IPendingResult <IProcessorCounterDataSource> pendingCounterData = trace.UseProcessorCounters();

            trace.Process();

            IProcessorCounterDataSource counterData = pendingCounterData.Result;

            if (!counterData.HasCycleCount)
            {
                Console.Error.WriteLine("Trace does not contain cycle count data.");
                return(2);
            }

            if (!counterData.HasInstructionCount)
            {
                Console.Error.WriteLine("Trace does not contain instruction count data.");
                return(2);
            }

            Dictionary <string, ulong> cyclesByProcess       = new Dictionary <string, ulong>();
            Dictionary <string, ulong> instructionsByProcess = new Dictionary <string, ulong>();

            foreach (IProcessorCounterContextSwitchDelta delta in counterData.ContextSwitchCounterDeltas)
            {
                string processName = delta.Thread?.Process?.ImageName ?? "Unknown";

                if (!cyclesByProcess.ContainsKey(processName))
                {
                    cyclesByProcess.Add(processName, 0);
                    instructionsByProcess.Add(processName, 0);
                }

                cyclesByProcess[processName]       += delta.CycleCount.Value;
                instructionsByProcess[processName] += delta.InstructionCount.Value;
            }

            foreach (string processName in cyclesByProcess.Keys.OrderBy(p => p, StringComparer.OrdinalIgnoreCase))
            {
                ulong   cycles               = cyclesByProcess[processName];
                ulong   instructions         = instructionsByProcess[processName];
                decimal cyclesPerInstruction = ((decimal)cycles) / instructions;
                Console.WriteLine($"{processName}: Cycles: {cycles}; Instructions: {instructions}; " +
                                  $"CPI: {cyclesPerInstruction:0.####}");
            }

            return(0);
        }
    }