/// <summary>
        /// Run the state machine to produce the stackSource given in the constructor.
        /// </summary>
        public void Execute()
        {
            // Get the trace log.
            TraceLog traceLog = m_Configuration.TraceLog;

            // Get the event dispatcher.
            TraceEventDispatcher eventDispatcher = traceLog.Events.GetSource();

            // Register computing resource event handlers.
            if ((m_ViewType == ComputingResourceViewType.CPU) || (m_ViewType == ComputingResourceViewType.ThreadTime))
            {
                eventDispatcher.Kernel.PerfInfoSample += OnCpuSample;
            }

            if (m_ViewType == ComputingResourceViewType.ThreadTime)
            {
                eventDispatcher.Kernel.ThreadStart   += OnThreadStart;
                eventDispatcher.Kernel.ThreadStop    += OnThreadEnd;
                eventDispatcher.Kernel.ThreadCSwitch += OnThreadCSwitch;
            }
            if (m_ViewType == ComputingResourceViewType.Allocations)
            {
                eventDispatcher.Clr.GCAllocationTick += OnGCAllocationTick;
            }

            // Register scenario event handlers.
            m_Configuration.ScenarioStateMachine.RegisterEventHandlers(eventDispatcher);

            // Process events.
            eventDispatcher.Process();

            // Sort samples.
            m_OutputStackSource.DoneAddingSamples();
        }
示例#2
0
        public bool LoadEvents(int procID, int sampleInterval100ns)
        {
            m_procID         = procID;
            m_SampleInterval = sampleInterval100ns / 10000.0;

            // Filter to process
            TraceEvents processEvents = m_traceLog.Events.Filter(FilterEvent);

            // Get Dispatcher
            TraceEventDispatcher source = processEvents.GetSource();

            kernelGuid = KernelTraceEventParser.ProviderGuid;

            // Hookup events
            source.Clr.All += OnClrEvent;

            ClrPrivateTraceEventParser clrPrivate = new ClrPrivateTraceEventParser(source);

            clrPrivate.All += OnClrPrivateEvent;

            KernelTraceEventParser kernel = source.Kernel;

            kernel.PerfInfoSample += delegate(SampledProfileTraceData data)
            {
                ThreadMemoryInfo thread = GetThread(data.ThreadID);

                thread.AddEvent(HeapEvents.CPUSample, data.TimeStampRelativeMSec);
            };

            kernel.VirtualMemAlloc += OnVirtualMem;
            kernel.VirtualMemFree  += OnVirtualMem;

            m_processLookup = new Dictionary <int, Microsoft.Diagnostics.Tracing.Analysis.TraceProcess>();

            // Process all events into GCProcess lookup dictionary
            Microsoft.Diagnostics.Tracing.Analysis.TraceLoadedDotNetRuntimeExtensions.NeedLoadedDotNetRuntimes(source);
            Microsoft.Diagnostics.Tracing.Analysis.TraceProcessesExtensions.AddCallbackOnProcessStart(source, proc =>
            {
                Microsoft.Diagnostics.Tracing.Analysis.TraceProcessesExtensions.SetSampleIntervalMSec(proc, sampleInterval100ns);
                proc.Log = m_traceLog;
            });
            source.Process();
            foreach (var proc in Microsoft.Diagnostics.Tracing.Analysis.TraceProcessesExtensions.Processes(source))
            {
                if (Microsoft.Diagnostics.Tracing.Analysis.TraceLoadedDotNetRuntimeExtensions.LoadedDotNetRuntime(proc) != null)
                {
                    m_processLookup.Add(proc.ProcessID, proc);
                }
            }

            // Get the process we want
            if (!m_processLookup.ContainsKey(procID))
            {
                return(false);
            }

            m_process = m_processLookup[procID];
            m_runtime = Microsoft.Diagnostics.Tracing.Analysis.TraceLoadedDotNetRuntimeExtensions.LoadedDotNetRuntime(m_process);
            return(true);
        }
示例#3
0
        private static void ProcessTrace(TraceEventDispatcher dispatcher)
        {
            dispatcher.Clr.All     += ProcessEvent;
            dispatcher.Kernel.All  += ProcessEvent;
            dispatcher.Dynamic.All += ProcessEvent;

            dispatcher.Process();
        }
示例#4
0
        public void RunTests()
        {
            // Get the configuration and start tracing.
            TraceConfiguration traceConfig = GenerateConfiguration();

            TraceControl.Enable(traceConfig);

            // Run the tests.
            foreach (EventSourceTest test in m_tests)
            {
                test.LogEvent();
            }

            // Stop tracing.
            TraceControl.Disable();

            // Open the trace file.
            string traceLogPath = TraceLog.CreateFromEventPipeDataFile(m_file.Path);

            using (TraceLog traceLog = new TraceLog(traceLogPath))
            {
                TraceEventDispatcher dispatcher = traceLog.Events.GetSource();

                dispatcher.Dynamic.All += delegate(TraceEvent data)
                {
                    if (data.ProviderName.EndsWith("Rundown"))
                    {
                        return;
                    }

                    if (data.ProviderName.Equals("Microsoft-DotNETCore-EventPipe"))
                    {
                        return;
                    }

                    Assert.True($"m_nextTestVerificationIndex({m_nextTestVerificationIndex}) < m_tests.Count({m_tests.Count})", m_nextTestVerificationIndex < m_tests.Count);
                    try
                    {
                        Console.WriteLine($"Verifying Event: {data.ToString()}");
                        m_tests[m_nextTestVerificationIndex].VerifyEvent(data);
                    }
                    catch
                    {
                        Console.WriteLine($"Failure during test '{m_tests[m_nextTestVerificationIndex].Name}'.");
                        throw;
                    }

                    m_nextTestVerificationIndex++;
                };

                dispatcher.Process();
                Assert.Equal("Test Count", m_tests.Count, m_nextTestVerificationIndex);
            }
        }
示例#5
0
    public EventStats(TraceEventDispatcher source)
        : this()
    {
        Action <TraceEvent> StatsCollector = delegate(TraceEvent data)
        {
            this.Increment(data);
        };

        // Add my parsers.
        source.Clr.All    += StatsCollector;
        source.Kernel.All += StatsCollector;
        new ClrRundownTraceEventParser(source).All += StatsCollector;
        new ClrStressTraceEventParser(source).All  += StatsCollector;
        new SymbolTraceEventParser(source).All     += StatsCollector;

        source.UnhandledEvent += StatsCollector;
        source.Process();
    }
示例#6
0
        public static ProcessLookup <JitCapProcess> Collect(JitCapCollector collector)
        {
            TraceEventDispatcher source = collector.Source;

            ProcessLookup <JitCapProcess> perProc = new ProcessLookup <JitCapProcess>();

            source.Kernel.PerfInfoSample += delegate(SampledProfileTraceData data)
            {
                JitCapProcess stats = perProc[data];
                if (stats != null)
                {
                    stats.ProcessCpuTimeMsec++;
                    string name = stats.GetSampledMethodName(collector, data);
                    stats.UpdateMethodCounts(name);
                }
            };
            source.Process();

            return(perProc);
        }
示例#7
0
        /// <summary>
        /// Execute the pinned object analyzer.
        /// </summary>
        internal void Execute(
            GCPinnedObjectViewType viewType)
        {
            // Process the heap snapshot, and populate the root table and process id.
            ProcessHeapSnapshot();

            // Instantiate the necessary trace event parsers.
            TraceEventDispatcher     eventDispatcher = _TraceLog.Events.GetSource();
            PerfViewTraceEventParser perfViewParser  = new PerfViewTraceEventParser(eventDispatcher);

            // we want the state of the heap at the time the snapshot was taken.
            perfViewParser.TriggerHeapSnapshot += delegate(TriggerHeapSnapshotTraceData data)
            {
                eventDispatcher.StopProcessing();
            };

            var heapWithPinningInfo = new PinningStackAnalysis(eventDispatcher, _TraceLog.Processes.GetProcess(_ProcessID, _TraceLog.SessionDuration.TotalMilliseconds), _StackSource, _Log);

            // Process the ETL file up until we detect that the heap snapshot was taken.
            eventDispatcher.Process();

            // Iterate through all pinned objects in the heap snapshot.
            foreach (KeyValuePair <Address, PinningRoot> pinnedPair in _RootTable)
            {
                // Try to match the object in the heap snapshot with an object in the ETL.
                PinningStackAnalysisObject liveObjectInfo = heapWithPinningInfo.GetPinningInfo(pinnedPair.Key);
                if (liveObjectInfo != null)
                {
                    // Found a match, write the appropriate call stacks.
                    if (viewType == GCPinnedObjectViewType.PinnedObjectAllocations)
                    {
                        WriteAllocationStack(pinnedPair.Key, pinnedPair.Value, liveObjectInfo);
                    }
                    else if (viewType == GCPinnedObjectViewType.PinnedHandles)
                    {
                        WritePinningStacks(pinnedPair.Key, pinnedPair.Value, liveObjectInfo);
                    }
                }
            }
        }
        /// <summary>
        /// This test collects a trace of itself and then performs some basic validation on the trace.
        /// </summary>
        public int Execute()
        {
            MySimpleEventSource MySimpleEventSource = new MySimpleEventSource(this);

            // Logging before tracing is enable - this should be ignored
            MySimpleEventSource.Request("Test 1");

            // Calculate the path to the config file.
            string configFileName = Assembly.GetEntryAssembly().GetName().Name + ".eventpipeconfig";
            string configFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, configFileName);

            Console.WriteLine("Calculated config file path: " + configFilePath);

            // Write the config file to disk.
            File.WriteAllText(configFilePath, GetConfigFileContents());
            Console.WriteLine("Wrote contents of config file.");

            // Wait few seconds to ensure that tracing has started.
            Console.WriteLine($"Waiting {TimeIntervalToReadConfigFile.TotalSeconds} seconds for the config file to be picked up by the next poll operation.");
            Thread.Sleep(TimeIntervalToReadConfigFile);

            // Do some work that we can look for in the trace.
            Console.WriteLine("Do some work that will be captured by the trace.");
            GC.Collect(2, GCCollectionMode.Forced);

            // Logging while tracing is enabled - this should NOT be ignored
            MySimpleEventSource.Request("Test 2");

            Console.WriteLine("Done with the work.");

            // Delete the config file to start tracing.
            File.Delete(configFilePath);
            Console.WriteLine("Deleted the config file.");

            // Build the full path to the trace file.
            string[] traceFiles = Directory.GetFiles(".", "*.netperf", SearchOption.TopDirectoryOnly);
            Assert.Equal("traceFiles.Length == 1", traceFiles.Length, 1);
            string traceFilePath = traceFiles[0];

            // Poll the file system and wait for the trace file to be written.
            Console.WriteLine("Wait for the config file deletion to be picked up and for the trace file to be written.");

            // Wait for 1 second, which is the poll time when tracing is enabled.
            Thread.Sleep(TimeSpan.FromSeconds(1));

            // Logging after tracing is disabled - this should be ignored
            MySimpleEventSource.Request("Test 3");

            // Poll for file size changes to the trace file itself.
            // When the size of the trace file hasn't changed for few seconds, consider it fully written out.
            Console.WriteLine($"Waiting for the trace file to be written. Poll every second to watch for {TimeIntervalToReadConfigFile.TotalSeconds} seconds of no file size changes.");
            long     lastSizeInBytes     = 0;
            DateTime timeOfLastChangeUTC = DateTime.UtcNow;

            do
            {
                FileInfo traceFileInfo      = new FileInfo(traceFilePath);
                long     currentSizeInBytes = traceFileInfo.Length;
                Console.WriteLine("Trace file size: " + ((double)currentSizeInBytes / BytesInOneMB));

                if (currentSizeInBytes > lastSizeInBytes)
                {
                    lastSizeInBytes     = currentSizeInBytes;
                    timeOfLastChangeUTC = DateTime.UtcNow;
                }

                Thread.Sleep(TimeSpan.FromSeconds(1));
            } while (DateTime.UtcNow.Subtract(timeOfLastChangeUTC) < TimeIntervalToReadConfigFile);

            // Use TraceEvent to consume the trace file and look for the work that we did.
            Console.WriteLine("Using TraceEvent to parse the file to find the work that was done during trace capture.");
            using (TraceEventDispatcher trace = TraceEventDispatcher.GetDispatcherFromFileName(traceFilePath))
            {
                InstallValidationCallbacks(trace);
                trace.Process();
            }

            // Clean-up the resulting trace file.
            File.Delete(traceFilePath);

            return(this.Pass() ? 100 : 10086);
        }
示例#9
0
 public void Append(MemoryGraph memoryGraph, TraceEventDispatcher source, int processId, double startTimeRelativeMSec = 0)
 {
     SetupCallbacks(memoryGraph, source, processId, startTimeRelativeMSec);
     source.Process();
     ConvertHeapDataToGraph();
 }
 public void Process()
 {
     Source.Process();
 }