private void OnThreadCSwitch(CSwitchTraceData data)
        {
            // Start blocking on the old thread.
            // Ignore the idle thread.
            if (data.OldThreadID != 0)
            {
                TraceThread oldThread = m_Configuration.TraceLog.Threads.GetThread(data.OldThreadID, data.TimeStampRelativeMSec);
                if (null != oldThread)
                {
                    ComputingResourceThreadState oldThreadState = m_ThreadState[(int)oldThread.ThreadIndex];
                    oldThreadState.LogBlockingStart(this, oldThread, data);
                }
            }

            // Stop blocking on the new thread.
            // Ignore the idle thread.
            if (data.ThreadID != 0)
            {
                TraceThread newThread = data.Thread();
                if (null != newThread)
                {
                    ComputingResourceThreadState newThreadState = m_ThreadState[(int)newThread.ThreadIndex];
                    newThreadState.LogBlockingStop(this, newThread, data);
                }
            }
        }
Exemplo n.º 2
0
 public ThreadWorkSpan(CSwitchTraceData switchData)
 {
     ProcessName = switchData.NewProcessName;
     ThreadId = switchData.NewThreadID;
     ProcessId = switchData.NewProcessID;
     ProcessorNumber = switchData.ProcessorNumber;
     AbsoluteTimestampMsc = switchData.TimeStampRelativeMSec;
     Priority = switchData.NewThreadPriority;
     WaitReason = (int)switchData.OldThreadWaitReason;
 }
Exemplo n.º 3
0
 public ThreadWorkSpan(CSwitchTraceData switchData)
 {
     ProcessName          = switchData.NewProcessName;
     ThreadId             = switchData.NewThreadID;
     ProcessId            = switchData.NewProcessID;
     ProcessorNumber      = switchData.ProcessorNumber;
     AbsoluteTimestampMsc = switchData.TimeStampRelativeMSec;
     Priority             = switchData.NewThreadPriority;
     WaitReason           = (int)switchData.OldThreadWaitReason;
 }
Exemplo n.º 4
0
        public override void ForEach(Func <EventRecord, bool> callback)
        {
            int    cnt       = 0;
            double startTime = StartTimeRelativeMSec;
            double endTime   = EndTimeRelativeMSec;
            // TODO could be more efficient about process filtering by getting all the processes that match.
            Regex  procRegex             = null;
            string procNameMustStartWith = null;

            if (ProcessFilterRegex != null)
            {
                // As an optimization, find the part that is just alphaNumeric
                procNameMustStartWith = Regex.Match(ProcessFilterRegex, @"^(\w*)").Groups[1].Value;
                procRegex             = new Regex(ProcessFilterRegex, RegexOptions.IgnoreCase);
            }

            Predicate <ETWEventRecord> textFilter = null;

            if (!string.IsNullOrWhiteSpace(TextFilterRegex))
            {
                string pat    = TextFilterRegex;
                bool   negate = false;
                if (pat.StartsWith("!"))
                {
                    negate = true;
                    pat    = pat.Substring(1);
                }
                var textRegex = new Regex(pat, RegexOptions.IgnoreCase);
                textFilter = delegate(ETWEventRecord eventRecord)
                {
                    bool match = eventRecord.Matches(textRegex);
                    return(negate ? !match : match);
                };
            }

            Dictionary <string, int> columnOrder = null;

            ColumnSums = null;
            if (ColumnsToDisplay != null)
            {
                columnOrder = new Dictionary <string, int>();
                for (int i = 0; i < ColumnsToDisplay.Count;)
                {
                    // Discard duplicate columns
                    if (columnOrder.ContainsKey(ColumnsToDisplay[i]))
                    {
                        ColumnsToDisplay.RemoveAt(i);
                        continue;
                    }
                    columnOrder.Add(ColumnsToDisplay[i], i);
                    i++;
                }

                ColumnSums = new double[ColumnsToDisplay.Count];
            }

            if (m_selectedEvents != null)
            {
                ETWEventRecord emptyEventRecord = new ETWEventRecord(this);
                var            startStopRecords = new Dictionary <StartStopKey, double>(10);

                // Figure out if you need m_activityComputer or not
                // Because it is moderately expensive, and not typically used, we only include the activity stuff
                // when you explicitly ask for it
                m_needsComputers = false;
                if (ColumnsToDisplay != null)
                {
                    foreach (string column in ColumnsToDisplay)
                    {
                        if (column == "*" || column == "ActivityInfo" || column == "StartStopActivity")
                        {
                            m_needsComputers = true;
                            break;
                        }
                    }
                }

                /***********************************************************************/
                /*                        The main event loop                          */
                EventVisitedVersion.CurrentVersion++;
                var source = m_tracelog.Events.FilterByTime(m_needsComputers ? 0 : startTime, endTime).GetSource(); // If you need computers, you need the events from the start.
                if (m_needsComputers)
                {
                    m_activityComputer          = new ActivityComputer(source, App.GetSymbolReader());
                    m_startStopActivityComputer = new StartStopActivityComputer(source, m_activityComputer);
                }
                source.AllEvents += delegate(TraceEvent data)
                {
                    // FilterByTime would cover this, however for m_needsComputer == true we may not be able to do it that way.
                    if (data.TimeStampRelativeMSec < startTime)
                    {
                        return;
                    }

                    double durationMSec       = -1;
                    var    eventFilterVersion = data.EventTypeUserData as EventVisitedVersion;

                    if (eventFilterVersion == null || eventFilterVersion.Version != EventVisitedVersion.CurrentVersion)
                    {
                        var eventName = data.ProviderName + "/" + data.EventName;

                        bool processButDontShow = false;
                        var  shouldKeep         = m_selectedAllEvents;
                        if (!shouldKeep)
                        {
                            if (m_selectedEvents.TryGetValue(eventName, out processButDontShow))
                            {
                                shouldKeep = true;
                            }
                        }

                        eventFilterVersion = new EventVisitedVersion(shouldKeep, processButDontShow);
                        if (!(data is UnhandledTraceEvent))
                        {
                            data.EventTypeUserData = eventFilterVersion;
                        }
                    }
                    if (!eventFilterVersion.ShouldProcess)
                    {
                        return;
                    }

                    // If this is a StopEvent compute the DURATION_MSEC
                    var opcode = data.Opcode;
                    var task   = data.Task;
                    CorelationOptions corelationOptions = CorelationOptions.None;
                    if (data.ProviderGuid == ClrTraceEventParser.ProviderGuid)
                    {
                        // Fix Suspend and restart events to line up to make durations.
                        if ((int)data.ID == 9)          // SuspendEEStart
                        {
                            corelationOptions = CorelationOptions.UseThreadContext;
                            task   = (TraceEventTask)0xFFFE;    // unique task
                            opcode = TraceEventOpcode.Start;
                        }
                        else if ((int)data.ID == 8)     // SuspendEEStop
                        {
                            corelationOptions = CorelationOptions.UseThreadContext;
                            task   = (TraceEventTask)0xFFFE;    // unique task  (used for both suspend and Suspend-Restart.
                            opcode = TraceEventOpcode.Stop;
                        }
                        else if ((int)data.ID == 3)     // RestartEEStop
                        {
                            corelationOptions = CorelationOptions.UseThreadContext;
                            task   = (TraceEventTask)0xFFFE;    // unique task
                            opcode = TraceEventOpcode.Stop;
                        }
                    }

                    if (data.ProviderGuid == httpServiceProviderGuid)
                    {
                        corelationOptions = CorelationOptions.UseActivityID;
                        if (opcode == (TraceEventOpcode)13)    // HttpServiceDeliver
                        {
                            opcode = TraceEventOpcode.Start;
                        }
                        // HttpServiceSendComplete  ZeroSend FastSend
                        else if (opcode == (TraceEventOpcode)51 || opcode == (TraceEventOpcode)22 || opcode == (TraceEventOpcode)21)
                        {
                            opcode = TraceEventOpcode.Stop;
                        }
                    }

                    if (data.ProviderGuid == systemDataProviderGuid)
                    {
                        corelationOptions = CorelationOptions.UseActivityID;
                        if ((int)data.ID == 1)               // BeginExecute
                        {
                            task   = (TraceEventTask)0xFFFE; // unique task but used for both BeginExecute and EndExecute.
                            opcode = TraceEventOpcode.Start;
                        }
                        else if ((int)data.ID == 2)          // EndExecute
                        {
                            task   = (TraceEventTask)0xFFFE; // unique task but used for both BeginExecute and EndExecute.
                            opcode = TraceEventOpcode.Stop;
                        }
                    }

                    if (opcode == TraceEventOpcode.Start || opcode == TraceEventOpcode.Stop)
                    {
                        // Figure out what we use as a correlater between the start and stop.
                        Guid contextID = GetCoorelationIDForEvent(data, corelationOptions);
                        var  key       = new StartStopKey(data.ProviderGuid, task, contextID);
                        if (opcode == TraceEventOpcode.Start)
                        {
                            startStopRecords[key] = data.TimeStampRelativeMSec;
                        }
                        else
                        {
                            double startTimeStamp;
                            if (startStopRecords.TryGetValue(key, out startTimeStamp))
                            {
                                durationMSec = data.TimeStampRelativeMSec - startTimeStamp;

                                // A bit of a hack.  WE use the same start event (SuspenEEStart) for two durations.
                                // Thus don't remove it after SuspendEEStop because we also use it for RestartEEStop.
                                if (!(task == (TraceEventTask)0xFFFE && (int)data.ID == 8)) // Is this the SuspendEEStop event?
                                {
                                    startStopRecords.Remove(key);
                                }
                            }
                        }
                    }

                    if (!eventFilterVersion.ShouldShow)
                    {
                        return;
                    }

                    if (procRegex != null)
                    {
                        CSwitchTraceData cSwitch = data as CSwitchTraceData;
                        if (!data.ProcessName.StartsWith(procNameMustStartWith, StringComparison.OrdinalIgnoreCase))
                        {
                            if (cSwitch == null)
                            {
                                return;
                            }
                            // Special case.  Context switches will work for both the old and the new process
                            if (!cSwitch.OldProcessName.StartsWith(procNameMustStartWith, StringComparison.OrdinalIgnoreCase))
                            {
                                return;
                            }
                        }

                        var fullProcessName = data.ProcessName;
                        if (!fullProcessName.StartsWith("("))
                        {
                            fullProcessName += " (" + data.ProcessID + ")";
                        }

                        if (!procRegex.IsMatch(fullProcessName))
                        {
                            if (cSwitch == null)
                            {
                                return;
                            }
                            // Special case.  Context switches will work for both the old and the new process
                            var fullOldProcessName = cSwitch.OldProcessName;
                            if (!fullOldProcessName.StartsWith("("))
                            {
                                fullOldProcessName += " (" + cSwitch.OldProcessName + ")";
                            }

                            if (!procRegex.IsMatch(fullOldProcessName))
                            {
                                return;
                            }
                        }
                    }

                    ETWEventRecord eventRecord = null;
                    if (textFilter != null)
                    {
                        eventRecord = new ETWEventRecord(this, data, columnOrder, NonRestFields, durationMSec);
                        if (!textFilter(eventRecord))
                        {
                            return;
                        }
                    }

                    cnt++;
                    if (MaxRet < cnt)
                    {
                        // We have exceeded our MaxRet, return an empty record.
                        eventRecord = emptyEventRecord;
                        eventRecord.m_timeStampRelativeMSec = data.TimeStampRelativeMSec;
                    }

                    if (eventRecord == null)
                    {
                        eventRecord = new ETWEventRecord(this, data, columnOrder, NonRestFields, durationMSec);
                    }

                    if (ColumnSums != null)
                    {
                        var fields = eventRecord.DisplayFields;
                        var min    = Math.Min(ColumnSums.Length, fields.Length);
                        for (int i = 0; i < min; i++)
                        {
                            string value = fields[i];
                            double asDouble;
                            if (value != null && double.TryParse(value, out asDouble))
                            {
                                ColumnSums[i] += asDouble;
                            }
                        }
                    }
                    if (!callback(eventRecord))
                    {
                        source.StopProcessing();
                    }
                };
                source.Process();
            }
        }