private void DoMetrics(LinuxEvent linuxEvent)
        {
            KeyValuePair <LinuxThreadState, LinuxEvent> sampleInfo;

            if (EndingStates.TryGetValue(linuxEvent.ThreadID, out sampleInfo))
            {
                linuxEvent.Period = linuxEvent.TimeMSec - sampleInfo.Value.TimeMSec;
            }

            // This is check for completed scheduler events, ones that start with prev_comm and have
            //   corresponding next_comm.
            if (linuxEvent.Kind == EventKind.Scheduler)
            {
                SchedulerEvent schedEvent = (SchedulerEvent)linuxEvent;
                if (EndingStates.ContainsKey(schedEvent.Switch.PreviousThreadID) &&
                    EndingStates[schedEvent.Switch.PreviousThreadID].Key == LinuxThreadState.CPU_TIME) // Blocking
                {
                    sampleInfo = EndingStates[schedEvent.Switch.PreviousThreadID];

                    EndingStates[schedEvent.Switch.PreviousThreadID] =
                        new KeyValuePair <LinuxThreadState, LinuxEvent>(LinuxThreadState.BLOCKED_TIME, linuxEvent);

                    linuxEvent.Period = linuxEvent.TimeMSec - sampleInfo.Value.TimeMSec;
                }

                if (EndingStates.TryGetValue(schedEvent.Switch.NextThreadID, out sampleInfo) &&
                    sampleInfo.Key == LinuxThreadState.BLOCKED_TIME) // Unblocking
                {
                    EndingStates[schedEvent.Switch.NextThreadID] =
                        new KeyValuePair <LinuxThreadState, LinuxEvent>(LinuxThreadState.CPU_TIME, linuxEvent);

                    // sampleInfo.Value.Period = linuxEvent.Time - sampleInfo.Value.Time;
                    AddThreadPeriod(linuxEvent.ThreadID, sampleInfo.Value.TimeMSec, linuxEvent.TimeMSec);
                }
            }
            else if (linuxEvent.Kind == EventKind.Cpu)
            {
                int threadid;
                if (EndingCpuUsage.TryGetValue(linuxEvent.CpuNumber, out threadid) && threadid != linuxEvent.ThreadID) // Unblocking
                {
                    if (EndingStates.TryGetValue(threadid, out sampleInfo))
                    {
                        EndingStates[threadid] =
                            new KeyValuePair <LinuxThreadState, LinuxEvent>(LinuxThreadState.CPU_TIME, linuxEvent);
                        sampleInfo.Value.Period = linuxEvent.TimeMSec - sampleInfo.Value.TimeMSec;
                        AddThreadPeriod(linuxEvent.ThreadID, sampleInfo.Value.TimeMSec, linuxEvent.TimeMSec);
                    }
                }
            }

            EndingCpuUsage[linuxEvent.CpuNumber] = linuxEvent.ThreadID;
        }
        /// <summary>
        /// Given a Linux event gotten from the trace, make its corresponding sample for the stack source.
        /// </summary>
        public StackSourceSample CreateSampleFor(LinuxEvent linuxEvent, BlockedTimeAnalyzer blockedTimeAnalyzer)
        {
            IEnumerable <Frame>       frames     = linuxEvent.CallerStacks;
            StackSourceCallStackIndex stackIndex = currentStackIndex;

            var sample = new StackSourceSample(this);

            sample.TimeRelativeMSec = linuxEvent.TimeMSec;
            sample.Metric           = 1;

            stackIndex        = InternFrames(frames.GetEnumerator(), stackIndex, linuxEvent.ProcessID, linuxEvent.ThreadID, blockedTimeAnalyzer);
            sample.StackIndex = stackIndex;

            return(sample);
        }
        /// <summary>
        /// Given a Linux event gotten from the trace, make its corresponding sample for the stack source.
        /// </summary>
        public LinuxPerfScriptStackSourceSample CreateSampleFor(LinuxEvent linuxEvent, BlockedTimeAnalyzer blockedTimeAnalyzer)
        {
            IEnumerable <Frame>       frames     = linuxEvent.CallerStacks;
            StackSourceCallStackIndex stackIndex = currentStackIndex;

            var sample = new LinuxPerfScriptStackSourceSample(this);

            sample.TimeRelativeMSec = linuxEvent.TimeMSec - StartTimeStampMSec;
            sample.Metric           = (float)linuxEvent.Period;
            sample.CpuNumber        = linuxEvent.CpuNumber;

            stackIndex        = InternFrames(frames.GetEnumerator(), stackIndex, linuxEvent.ProcessID, linuxEvent.ThreadID, doThreadTime ? blockedTimeAnalyzer : null);
            sample.StackIndex = stackIndex;

            return(sample);
        }
        public void UpdateThreadState(LinuxEvent linuxEvent)
        {
            if (TimeStamp < linuxEvent.TimeMSec)
            {
                TimeStamp = linuxEvent.TimeMSec;
            }

            if (!BeginningStates.ContainsKey(linuxEvent.ThreadID))
            {
                BeginningStates.Add(
                    linuxEvent.ThreadID,
                    new KeyValuePair <LinuxThreadState, LinuxEvent>(LinuxThreadState.CPU_TIME, linuxEvent));

                EndingStates[linuxEvent.ThreadID] = BeginningStates[linuxEvent.ThreadID];
            }

            DoMetrics(linuxEvent);
        }
 public void LinuxEventSampleAssociation(LinuxEvent linuxEvent, StackSourceSample sample)
 {
     LinuxEventSamples[linuxEvent] = sample;
 }
        private void DoMetrics(LinuxEvent linuxEvent)
        {
            KeyValuePair <LinuxThreadState, LinuxEvent> sampleInfo;

            // This is check for completed scheduler events, ones that start with prev_comm and have
            //   corresponding next_comm.
            if (linuxEvent.Kind == EventKind.Scheduler)
            {
                SchedulerEvent schedEvent = (SchedulerEvent)linuxEvent;
                if (EndingStates.ContainsKey(schedEvent.Switch.PreviousThreadID) &&
                    EndingStates[schedEvent.Switch.PreviousThreadID].Key == LinuxThreadState.CPU_TIME) // Blocking
                {
                    // PreviousThreadID is now blocking.  linuxEvent contains its blocking stack, so save it here.
                    // When it unblocks (becomes NextThreadID below, we'll log a sample for it.)
                    EndingStates[schedEvent.Switch.PreviousThreadID] =
                        new KeyValuePair <LinuxThreadState, LinuxEvent>(LinuxThreadState.BLOCKED_TIME, linuxEvent);
                }

                if (EndingStates.TryGetValue(schedEvent.Switch.NextThreadID, out sampleInfo) &&
                    sampleInfo.Key == LinuxThreadState.BLOCKED_TIME) // Unblocking
                {
                    sampleInfo.Value.Period = linuxEvent.TimeMSec - sampleInfo.Value.TimeMSec;
                    AddThreadPeriod(sampleInfo.Value.ThreadID, sampleInfo.Value.TimeMSec, linuxEvent.TimeMSec);
                    StackSource.AddSample(StackSource.CreateSampleFor(sampleInfo.Value, this));

                    EndingStates[schedEvent.Switch.NextThreadID] =
                        new KeyValuePair <LinuxThreadState, LinuxEvent>(LinuxThreadState.CPU_TIME, linuxEvent);
                }
            }
            else if (linuxEvent.Kind == EventKind.ThreadExit)
            {
                ThreadExitEvent exitEvent = (ThreadExitEvent)linuxEvent;
                if (EndingStates.TryGetValue(exitEvent.Exit.ThreadID, out sampleInfo))
                {
                    if (sampleInfo.Key == LinuxThreadState.BLOCKED_TIME) // Blocked on exit
                    {
                        sampleInfo.Value.Period = linuxEvent.TimeMSec - sampleInfo.Value.TimeMSec;
                        AddThreadPeriod(sampleInfo.Value.ThreadID, sampleInfo.Value.TimeMSec, linuxEvent.TimeMSec);
                        StackSource.AddSample(StackSource.CreateSampleFor(sampleInfo.Value, this));
                    }
                    else // Unblocked on exit
                    {
                        linuxEvent.Period = linuxEvent.TimeMSec - sampleInfo.Value.TimeMSec;
                        StackSource.AddSample(StackSource.CreateSampleFor(linuxEvent, this));
                    }

                    // Remove the thread so that any events that might come after the exit are ignored.
                    EndingStates.Remove(exitEvent.Exit.ThreadID);
                }
            }
            else if (linuxEvent.Kind == EventKind.Cpu)
            {
                // Keep track of the last CPU sample for each CPU, and use its timestamp
                // to determine how much weight to give the sample.
                if (LastCpuUsage.TryGetValue(linuxEvent.CpuNumber, out LinuxEvent lastCpuEvent))
                {
                    lastCpuEvent.Period = linuxEvent.TimeMSec - lastCpuEvent.TimeMSec;
                    StackSource.AddSample(StackSource.CreateSampleFor(lastCpuEvent, this));
                }

                LastCpuUsage[linuxEvent.CpuNumber] = linuxEvent;
            }
        }