Exemplo n.º 1
0
    internal void Increment(TraceEvent data)
    {
#if DEBUG
        // Debug.Assert((byte)data.opcode != unchecked((byte)-1));        // Means PrepForCallback not done.
        Debug.Assert(data.TaskName != "ERRORTASK");
        Debug.Assert(data.OpcodeName != "ERROROPCODE");
#endif
        Count++;
        TaskStats task = this[data.TaskName];
        if (task.ProviderName == null)
        {
            task.ProviderName = data.ProviderName;
        }

        CallStackIndex index    = data.CallStackIndex();
        bool           hasStack = (index != CallStackIndex.Invalid);
        if (hasStack)
        {
            StackCount++;
        }
        task.Increment(data.OpcodeName, hasStack);
        StackWalkTraceData asStackWalk = data as StackWalkTraceData;
        if (asStackWalk != null)
        {
            StackWalkStats stackWalkStats = task.ExtraData as StackWalkStats;
            if (stackWalkStats == null)
            {
                stackWalkStats = new StackWalkStats();
                task.ExtraData = stackWalkStats;
            }
            stackWalkStats.Log(asStackWalk);
        }
    }
Exemplo n.º 2
0
        private void OnObjectAllocated(TraceEvent data, Address objectID, Address classID, long size, long representativeSize)
        {
            if (data.ProcessID != m_processID)
            {
                return;
            }

            Debug.Assert(GetObjectInfo(objectID) == null);            // new objects should be unique.
            var objectData = AllocateObject();

            var stackIndex = m_stackSource.GetCallStack(data.CallStackIndex(), data);

            // Add object type as a pseudo-frame to the stack
            TypeInfo typeInfo;

            if (!m_classNamesAsFrames.TryGetValue(classID, out typeInfo))
            {
                typeInfo.FrameIdx = m_stackSource.Interner.FrameIntern("Type <Unknown>");
            }

            objectData.ClassFrame = typeInfo.FrameIdx;
            objectData.AllocStack = stackIndex;

            objectData.Size = (int)size;
            objectData.RepresentativeSize = (int)representativeSize;

            var timeStamp = data.TimeStampRelativeMSec;
            // Insure that timeStamps move forward in time and are unique, so they can be used as object IDs.
            var verySmall = 1;

            while (timeStamp <= m_lastAllocTimeRelativeMSec)
            {
                timeStamp = m_lastAllocTimeRelativeMSec + verySmall * .0000001; // Add a 10th of a ns.
                verySmall = verySmall * 2;                                      // Depending on how long the trace has run, this may not change timestamp, so keep making it bigger until it does.
            }
            m_lastAllocTimeRelativeMSec = timeStamp;

            objectData.AllocationTimeRelativeMSec = timeStamp;

            Debug.WriteLine(string.Format("Object Allocated {0:x} Size {1:x} Rep {2:x} {3}", objectID, size, representativeSize, typeInfo.TypeName));
            m_currentHeapSize += (uint)objectData.RepresentativeSize;
            if (OnObjectCreate != null)
            {
                if (!OnObjectCreate(objectID, objectData))
                {
                    return;
                }
            }

            var allocGen = 0;

            if (objectData.Size >= 85000)     // Large objects go into Gen 2
            {
                allocGen = 2;
            }

            m_ObjsInGen[allocGen][(Address)objectID] = objectData;       // Put the object into Gen 0;
        }
Exemplo n.º 3
0
        private StackSourceCallStackIndex GetStack(TraceEvent event_)
        {
            // Console.WriteLine("Getting Stack for sample at {0:f4}", sample.TimeStampRelativeMSec);
            int ret = (int)event_.CallStackIndex();

            if (ret == (int)CallStackIndex.Invalid)
            {
                var thread = event_.Thread();
                if (thread == null)
                {
                    return(StackSourceCallStackIndex.Invalid);
                }

                // If the event is a sample profile, or page fault we can make a one element stack with the EIP in the event
                CodeAddressIndex codeAddrIdx = CodeAddressIndex.Invalid;
                var asSampleProfile          = event_ as SampledProfileTraceData;
                if (asSampleProfile != null)
                {
                    codeAddrIdx = asSampleProfile.IntructionPointerCodeAddressIndex();
                }
                else
                {
                    var asPageFault = event_ as MemoryHardFaultTraceData;
                    if (asPageFault != null)
                    {
                        codeAddrIdx = asSampleProfile.IntructionPointerCodeAddressIndex();
                    }
                }

                if (codeAddrIdx != CodeAddressIndex.Invalid)
                {
                    // Encode the code address for the given thread.
                    int pseudoStackIndex = GetPseudoStack(thread.ThreadIndex, codeAddrIdx);
                    // Psuedostacks happen after all the others.
                    if (0 <= pseudoStackIndex)
                    {
                        ret = m_log.CallStacks.Count + 2 * m_log.Threads.Count + m_log.Processes.Count + pseudoStackIndex;
                    }
                }

                // If we have run out of pseudo-stacks, we encode the stack as being at the thread.
                if (ret == (int)CallStackIndex.Invalid)
                {
                    ret = m_log.CallStacks.Count + (int)thread.ThreadIndex;
                }
            }
            else
            {
                // We expect the thread we get when looking at the CallStack to match the thread of the event.
                Debug.Assert(m_log.CallStacks.Thread((CallStackIndex)ret).ThreadID == event_.ThreadID);
                Debug.Assert(event_.Thread().Process.ProcessID == event_.ProcessID);
            }
            ret = ret + (int)StackSourceCallStackIndex.Start;
            return((StackSourceCallStackIndex)ret);
        }
Exemplo n.º 4
0
        private StackSourceCallStackIndex GetStack(TraceEvent event_)
        {
            // Console.WriteLine("Getting Stack for sample at {0:f4}", sample.TimeStampRelativeMSec);
            var ret = (int)event_.CallStackIndex();

            if (ret == (int)CallStackIndex.Invalid)
            {
                var thread = event_.Thread();
                if (thread == null)
                {
                    return(StackSourceCallStackIndex.Invalid);
                }

                // If the event is a sample profile, or page fault we can make a one element stack with the EIP in the event
                CodeAddressIndex codeAddrIdx = CodeAddressIndex.Invalid;
                var asSampleProfile          = event_ as SampledProfileTraceData;
                if (asSampleProfile != null)
                {
                    codeAddrIdx = asSampleProfile.IntructionPointerCodeAddressIndex();
                }
                else
                {
                    var asPageFault = event_ as PageFaultHardFaultTraceData;
                    if (asPageFault != null)
                    {
                        codeAddrIdx = asSampleProfile.IntructionPointerCodeAddressIndex();
                    }
                }

                if (codeAddrIdx != CodeAddressIndex.Invalid)
                {
                    // Encode the code address for the given thread.
                    int pseudoStackIndex = GetPseudoStack(thread.ThreadIndex, codeAddrIdx);
                    if (pseudoStackIndex < 0)
                    {
                        return(StackSourceCallStackIndex.Start);
                    }

                    // Psuedostacks happen after all the others.
                    ret = m_log.CallStacks.MaxCallStackIndex + 2 * m_log.Threads.MaxThreadIndex + m_log.Processes.MaxProcessIndex + pseudoStackIndex;
                }
                else
                {
                    // Otherwise we encode the stack as being at the thread.
                    ret = m_log.CallStacks.MaxCallStackIndex + (int)thread.ThreadIndex;
                }
            }
            ret = ret + (int)StackSourceCallStackIndex.Start;
            return((StackSourceCallStackIndex)ret);
        }
        /// <summary>
        /// Mark the thread as unblocked.
        /// </summary>
        public void LogBlockingStop(
            ComputingResourceStateMachine stateMachine,
            TraceThread thread,
            TraceEvent data)
        {
            if ((null == stateMachine) || (null == thread) || (null == data))
            {
                return;
            }

            // Only add a sample if the thread was blocked.
            if (ThreadBlocked)
            {
                StackSourceSample            sample      = stateMachine.Sample;
                MutableTraceEventStackSource stackSource = stateMachine.StackSource;

                // Set the time and metric.
                sample.TimeRelativeMSec = this.BlockTimeStartRelativeMSec;
                sample.Metric           = (float)(data.TimeStampRelativeMSec - this.BlockTimeStartRelativeMSec);

                /* Generate the stack trace. */

                CallStackIndex            traceLogCallStackIndex = data.CallStackIndex();
                ScenarioThreadState       scenarioThreadState    = stateMachine.Configuration.ScenarioThreadState[ThreadIndex];
                StackSourceCallStackIndex callStackIndex         = scenarioThreadState.GetCallStackIndex(stateMachine.StackSource, thread, data);

                // Add the thread.
                StackSourceFrameIndex threadFrameIndex = stackSource.Interner.FrameIntern(thread.VerboseThreadName);
                callStackIndex = stackSource.Interner.CallStackIntern(threadFrameIndex, callStackIndex);

                // Add the full call stack.
                callStackIndex = stackSource.GetCallStack(traceLogCallStackIndex, callStackIndex, null);

                // Add Pseud-frames representing the kind of resource.
                StackSourceFrameIndex frameIndex = stackSource.Interner.FrameIntern("BLOCKED TIME");
                callStackIndex = stackSource.Interner.CallStackIntern(frameIndex, callStackIndex);

                // Add the call stack to the sample.
                sample.StackIndex = callStackIndex;

                // Add the sample.
                stackSource.AddSample(sample);

                // Mark the thread as executing.
                BlockTimeStartRelativeMSec = -1;
            }
        }
        /// <summary>
        /// Log a CPU sample on this thread.
        /// </summary>
        public void LogCPUSample(
            ComputingResourceStateMachine stateMachine,
            TraceThread thread,
            TraceEvent data)
        {
            if ((null == stateMachine) || (null == thread) || (null == data))
            {
                return;
            }

            StackSourceSample sample = stateMachine.Sample;

            sample.Metric           = 1;
            sample.TimeRelativeMSec = data.TimeStampRelativeMSec;
            MutableTraceEventStackSource stackSource = stateMachine.StackSource;

            // Attempt to charge the CPU to a request.
            CallStackIndex traceLogCallStackIndex = data.CallStackIndex();

            ScenarioThreadState       scenarioThreadState = stateMachine.Configuration.ScenarioThreadState[ThreadIndex];
            StackSourceCallStackIndex callStackIndex      = scenarioThreadState.GetCallStackIndex(stackSource, thread, data);

            // Add the thread.
            StackSourceFrameIndex threadFrameIndex = stackSource.Interner.FrameIntern(thread.VerboseThreadName);

            callStackIndex = stackSource.Interner.CallStackIntern(threadFrameIndex, callStackIndex);

            // Rest of the stack.
            // NOTE: Do not pass a call stack map into this method, as it will skew results.
            callStackIndex = stackSource.GetCallStack(traceLogCallStackIndex, callStackIndex, null);

            // Add the CPU frame.
            StackSourceFrameIndex cpuFrameIndex = stackSource.Interner.FrameIntern("CPU");

            callStackIndex = stackSource.Interner.CallStackIntern(cpuFrameIndex, callStackIndex);

            // Add the sample.
            sample.StackIndex = callStackIndex;
            stackSource.AddSample(sample);
        }
Exemplo n.º 7
0
            internal ETWEventRecord(ETWEventSource source, TraceEvent data, Dictionary <string, int> columnOrder, int nonRestFields, double durationMSec)
                : base(nonRestFields)
            {
                m_source      = source;
                m_name        = data.ProviderName + "/" + data.EventName;
                m_processName = data.ProcessName;
                if (!m_processName.StartsWith("("))
                {
                    m_processName += " (" + data.ProcessID + ")";
                }

                m_timeStampRelativeMSec = data.TimeStampRelativeMSec;
                m_idx = data.EventIndex;

                // Compute the data column
                var restString = new StringBuilder();

                // Deal with the special HasStack, ThreadID and ActivityID, DataLength fields;
                var hasStack = data.CallStackIndex() != CallStackIndex.Invalid;

                if (hasStack)
                {
                    AddField("HasStack", hasStack.ToString(), columnOrder, restString);
                }

                var asCSwitch = data as CSwitchTraceData;

                if (asCSwitch != null)
                {
                    AddField("HasBlockingStack", (asCSwitch.BlockingStack() != CallStackIndex.Invalid).ToString(), columnOrder, restString);
                }

                AddField("ThreadID", data.ThreadID.ToString("n0"), columnOrder, restString);
                AddField("ProcessorNumber", data.ProcessorNumber.ToString(), columnOrder, restString);

                if (0 < durationMSec)
                {
                    AddField("DURATION_MSEC", durationMSec.ToString("n3"), columnOrder, restString);
                }

                var payloadNames = data.PayloadNames;

                if (payloadNames.Length == 0 && data.EventDataLength != 0)
                {
                    // WPP events look classic and use the EventID as their discriminator
                    if (data.IsClassicProvider && data.ID != 0)
                    {
                        AddField("EventID", ((int)data.ID).ToString(), columnOrder, restString);
                    }

                    AddField("DataLength", data.EventDataLength.ToString(), columnOrder, restString);
                }

                try
                {
                    for (int i = 0; i < payloadNames.Length; i++)
                    {
                        AddField(payloadNames[i], data.PayloadString(i), columnOrder, restString);
                    }
                }
                catch (Exception e)
                {
                    AddField("ErrorParsingFields", e.Message, columnOrder, restString);
                }

                var message = data.FormattedMessage;

                if (message != null)
                {
                    AddField("FormattedMessage", message, columnOrder, restString);
                }

                if (source.m_needsComputers)
                {
                    TraceThread thread = data.Thread();
                    if (thread != null)
                    {
                        TraceActivity activity = source.m_activityComputer.GetCurrentActivity(thread);
                        if (activity != null)
                        {
                            string id = activity.ID;
                            if (Math.Abs(activity.StartTimeRelativeMSec - m_timeStampRelativeMSec) < .0005)
                            {
                                id = "^" + id;              // Indicates it is at the start of the task.
                            }

                            AddField("ActivityInfo", id, columnOrder, restString);
                        }

                        var startStopActivity = source.m_startStopActivityComputer.GetCurrentStartStopActivity(thread, data);
                        if (startStopActivity != null)
                        {
                            string name       = startStopActivity.Name;
                            string parentName = "$";
                            if (startStopActivity.Creator != null)
                            {
                                parentName = startStopActivity.Creator.Name;
                            }

                            AddField("StartStopActivity", name + "/P=" + parentName, columnOrder, restString);
                        }
                    }
                }

                // We pass 0 as the process ID for creating the activityID because we want uniform syntax.
                if (data.ActivityID != Guid.Empty)
                {
                    AddField("ActivityID", StartStopActivityComputer.ActivityPathString(data.ActivityID), columnOrder, restString);
                }

                Guid relatedActivityID = data.RelatedActivityID;

                if (relatedActivityID != Guid.Empty)
                {
                    AddField("RelatedActivityID", StartStopActivityComputer.ActivityPathString(data.RelatedActivityID), columnOrder, restString);
                }

                if (data.ContainerID != null)
                {
                    AddField("ContainerID", data.ContainerID, columnOrder, restString);
                }

                m_asText = restString.ToString();
            }