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); }
ThreadMemoryInfo GetThread(int threadID) { ThreadMemoryInfo ret; if (!m_threadInfo.TryGetValue(threadID, out ret)) { ret = new ThreadMemoryInfo(this, threadID); ret.SampleInterval = m_SampleInterval; m_threadInfo[threadID] = ret; } return(ret); }
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 ProcessLookup <GCProcess>(); // Process all events into GCProcess lookup dictionary GCProcess.Collect(source, sampleInterval100ns, m_processLookup, null, false, m_traceLog); // Get the process we want return(m_processLookup.TryGetByID(procID, out m_gcProcess)); }
public void DrawThread(int y, ThreadMemoryInfo thread, bool drawLegend, bool drawMarker) { List <HeapEventData> events = thread.m_events; int count = events.Count; m_barY = y; if (count > 1) { double start = events[0].m_time; double end = events[count - 1].m_time; if (drawLegend) { string name = thread.Name; if (!String.IsNullOrEmpty(name)) { if (name.StartsWith(".Net ", StringComparison.OrdinalIgnoreCase)) { name = name.Substring(5); } } DrawText(5, y + 8, String.Format("{0}, {1}, {2} ms", thread.ThreadID, name, thread.CpuSample), 9); return; } if ((start > m_barT1) || (end < m_barT0)) { return; } if (end > m_barT1) { end = m_barT1; } DrawText(MapX(end) + 5, y, String.Format("Thread {0}, {1}, {2} ms", thread.ThreadID, thread.Name, thread.CpuSample), 8); DrawRect(m_blue25, MapX(start), y, MapXDelta(end - start), m_barH); BarInterval cpuSample = new BarInterval(this, Brushes.Black); BarInterval contention = new BarInterval(this, Brushes.Red); BarInterval waitBgc = new BarInterval(this, Brushes.Yellow); double half = thread.SampleInterval / 2; for (int i = 0; i < count; i++) { HeapEventData evt = events[i]; double tick = evt.m_time; switch (evt.m_event) { case HeapEvents.CPUSample: cpuSample.Start(tick - half); cpuSample.End(tick + half); break; case HeapEvents.ContentionStart: contention.Start(tick); break; case HeapEvents.ContentionStop: contention.End(tick); break; case HeapEvents.BGCAllocWaitStart: waitBgc.Start(tick); break; case HeapEvents.BGCAllocWaitStop: waitBgc.End(tick); break; default: break; } } cpuSample.Draw(); contention.Draw(); waitBgc.Draw(); if (drawMarker) { DrawMarkers(y, events); } } }
internal void OnClrPrivateEvent(TraceEvent data) { TraceEventID eventID = data.ID; HeapEvents heapEvent = HeapEvents.Unknown; // TODO don't use IDs but use individual callbacks. const TraceEventID GCDecisionEventID = (TraceEventID)1; const TraceEventID GCSettingsEventID = (TraceEventID)2; const TraceEventID GCOptimizedEventID = (TraceEventID)3; const TraceEventID GCPerHeapHistoryEventID = (TraceEventID)4; const TraceEventID GCGlobalHeapHistoryEventID = (TraceEventID)5; const TraceEventID GCJoinEventID = (TraceEventID)6; const TraceEventID GCMarkStackRootsEventID = (TraceEventID)7; const TraceEventID GCMarkFinalizeQueueRootsEventID = (TraceEventID)8; const TraceEventID GCMarkHandlesEventID = (TraceEventID)9; const TraceEventID GCMarkCardsEventID = (TraceEventID)10; const TraceEventID GCBGCStartEventID = (TraceEventID)11; const TraceEventID GCBGC1stNonCondStopEventID = (TraceEventID)12; const TraceEventID GCBGC1stConStopEventID = (TraceEventID)13; const TraceEventID GCBGC2ndNonConStartEventID = (TraceEventID)14; const TraceEventID GCBGC2ndNonConStopEventID = (TraceEventID)15; const TraceEventID GCBGC2ndConStartEventID = (TraceEventID)16; const TraceEventID GCBGC2ndConStopEventID = (TraceEventID)17; const TraceEventID GCBGCPlanStopEventID = (TraceEventID)18; const TraceEventID GCBGCSweepStopEventID = (TraceEventID)19; const TraceEventID GCBGCDrainMarkEventID = (TraceEventID)20; const TraceEventID GCBGCRevisitEventID = (TraceEventID)21; const TraceEventID GCBGCOverflowEventID = (TraceEventID)22; const TraceEventID GCBGCAllocWaitStartEventID = (TraceEventID)23; const TraceEventID GCBGCAllocWaitStopEventID = (TraceEventID)24; const TraceEventID GCFullNotifyEventID = (TraceEventID)25; switch (eventID) { case GCDecisionEventID: heapEvent = HeapEvents.GCDecision; break; case GCSettingsEventID: heapEvent = HeapEvents.GCSettings; break; case GCOptimizedEventID: heapEvent = HeapEvents.GCOptimized; { GCOptimizedTraceData mdata = data as GCOptimizedTraceData; if (mdata.GenerationNumber == 0) { m_g0Budget = mdata.DesiredAllocation; m_g0Alloc = mdata.NewAllocation; } else { m_g3Budget = mdata.DesiredAllocation; m_g3Alloc = mdata.NewAllocation; } } break; case GCPerHeapHistoryEventID: heapEvent = HeapEvents.GCPerHeapHistory; break; case GCGlobalHeapHistoryEventID: heapEvent = HeapEvents.GCGlobalHeapHistory; { GCGlobalHeapHistoryTraceData mdata = data as GCGlobalHeapHistoryTraceData; m_heapCount = mdata.NumHeaps; } break; case GCJoinEventID: heapEvent = HeapEvents.GCJoin; break; case GCMarkStackRootsEventID: heapEvent = HeapEvents.GCMarkStackRoots; break; case GCMarkFinalizeQueueRootsEventID: heapEvent = HeapEvents.GCMarkFinalizeQueueRoots; break; case GCMarkHandlesEventID: heapEvent = HeapEvents.GCMarkHandles; break; case GCMarkCardsEventID: heapEvent = HeapEvents.GCMarkCards; break; case GCBGCStartEventID: heapEvent = HeapEvents.BGCBegin; break; case GCBGC1stNonCondStopEventID: heapEvent = HeapEvents.BGC1stNonCondEnd; break; case GCBGC1stConStopEventID: heapEvent = HeapEvents.BGC1stConEnd; break; case GCBGC2ndNonConStartEventID: heapEvent = HeapEvents.BGC2ndNonConBegin; break; case GCBGC2ndNonConStopEventID: heapEvent = HeapEvents.BGC2ndNonConEnd; break; case GCBGC2ndConStartEventID: heapEvent = HeapEvents.BGC2ndConBegin; break; case GCBGC2ndConStopEventID: heapEvent = HeapEvents.BGC2ndConEnd; break; case GCBGCPlanStopEventID: heapEvent = HeapEvents.BGCPlanEnd; break; case GCBGCSweepStopEventID: heapEvent = HeapEvents.BGCSweepEnd; break; case GCBGCDrainMarkEventID: heapEvent = HeapEvents.BGCDrainMark; break; case GCBGCRevisitEventID: heapEvent = HeapEvents.BGCRevisit; break; case GCBGCOverflowEventID: heapEvent = HeapEvents.BGCOverflow; break; case GCBGCAllocWaitStartEventID: heapEvent = HeapEvents.BGCAllocWaitStart; break; case GCBGCAllocWaitStopEventID: heapEvent = HeapEvents.BGCAllocWaitStop; break; case GCFullNotifyEventID: heapEvent = HeapEvents.GCFullNotify; break; // FinalizeObject, // CCWRefCountChange, // SetGCHandle, // DestroyGCHandle, default: break; } if (heapEvent != HeapEvents.Unknown) { ThreadMemoryInfo thread = GetThread(data.ThreadID); thread.AddEvent(heapEvent, data.TimeStampRelativeMSec); } }
internal void OnClrEvent(TraceEvent data) { TraceEventID eventID = data.ID; HeapEvents heapEvent = HeapEvents.Unknown; // TODO don't use IDs but use individual callbacks. const TraceEventID GCStartEventID = (TraceEventID)1; const TraceEventID GCStopEventID = (TraceEventID)2; const TraceEventID GCRestartEEStopEventID = (TraceEventID)3; const TraceEventID GCHeapStatsEventID = (TraceEventID)4; const TraceEventID GCCreateSegmentEventID = (TraceEventID)5; const TraceEventID GCFreeSegmentEventID = (TraceEventID)6; const TraceEventID GCRestartEEStartEventID = (TraceEventID)7; const TraceEventID GCSuspendEEStopEventID = (TraceEventID)8; const TraceEventID GCSuspendEEStartEventID = (TraceEventID)9; const TraceEventID GCAllocationTickEventID = (TraceEventID)10; const TraceEventID GCCreateConcurrentThreadEventID = (TraceEventID)11; const TraceEventID GCTerminateConcurrentThreadEventID = (TraceEventID)12; const TraceEventID GCFinalizersStopEventID = (TraceEventID)13; const TraceEventID GCFinalizersStartEventID = (TraceEventID)14; const TraceEventID ContentionStartEventID = (TraceEventID)81; const TraceEventID ContentionStopEventID = (TraceEventID)91; switch (eventID) { case GCStartEventID: { var mdata = data as Microsoft.Diagnostics.Tracing.Parsers.Clr.GCStartTraceData; if (mdata != null) { GcEventExtra extra = GetGcEventExtra(mdata.Count); extra.GCStartIndex = data.EventIndex; extra.GCStartThread = data.Thread(); } } heapEvent = HeapEvents.GCStart; break; case GCStopEventID: heapEvent = HeapEvents.GCEnd; break; case GCRestartEEStartEventID: heapEvent = HeapEvents.GCRestartEEBegin; break; case GCRestartEEStopEventID: heapEvent = HeapEvents.GCRestartEEEnd; break; case GCHeapStatsEventID: heapEvent = HeapEvents.GCHeapStats; break; case GCCreateSegmentEventID: heapEvent = HeapEvents.GCCreateSegment; break; case GCFreeSegmentEventID: heapEvent = HeapEvents.GCFreeSegment; break; case GCSuspendEEStartEventID: heapEvent = HeapEvents.GCSuspendEEBegin; break; case GCSuspendEEStopEventID: heapEvent = HeapEvents.GCSuspendEEEnd; break; case GCAllocationTickEventID: heapEvent = HeapEvents.GCAllocationTick; { GCAllocationTickTraceData mdata = data as GCAllocationTickTraceData; AllocationTick(mdata, mdata.AllocationKind == GCAllocationKind.Large, mdata.GetAllocAmount(ref seenBadAlloc) / OneMBD); } break; case GCCreateConcurrentThreadEventID: heapEvent = HeapEvents.GCCreateConcurrentThread; break; case GCTerminateConcurrentThreadEventID: heapEvent = HeapEvents.GCTerminateConcurrentThread; break; case GCFinalizersStartEventID: heapEvent = HeapEvents.GCFinalizersBegin; break; case GCFinalizersStopEventID: heapEvent = HeapEvents.GCFinalizersEnd; break; case ContentionStartEventID: heapEvent = HeapEvents.ContentionStart; break; case ContentionStopEventID: heapEvent = HeapEvents.ContentionStop; break; default: break; } if (heapEvent != HeapEvents.Unknown) { ThreadMemoryInfo thread = GetThread(data.ThreadID); thread.AddEvent(heapEvent, data.TimeStampRelativeMSec); } }