Esempio n. 1
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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
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 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));
        }
Esempio n. 4
0
        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);
                }
            }
        }
Esempio n. 5
0
        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);
            }
        }
Esempio n. 6
0
        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);
            }
        }