/// <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);
        }
        protected virtual void DoInterning()
        {
            BlockedTimeAnalyzer blockedTimeAnalyzer = doThreadTime ? new BlockedTimeAnalyzer() : null;

            foreach (var linuxEvent in parser.ParseSkippingPreamble(masterSource))
            {
                blockedTimeAnalyzer?.UpdateThreadState(linuxEvent);
                AddSample(CreateSampleFor(linuxEvent, blockedTimeAnalyzer));
            }

            blockedTimeAnalyzer?.FinishAnalyzing();
            // TODO: Sort things in blocked time analyzer
            // this.threadBlockedPeriods.Sort((x, y) => x.StartTime.CompareTo(y.StartTime));

            TotalBlockedTime = blockedTimeAnalyzer != null ? blockedTimeAnalyzer.TotalBlockedTime : -1;
        }
        private StackSourceCallStackIndex InternFrames(IEnumerator <Frame> frameIterator, StackSourceCallStackIndex stackIndex, int processID, int?threadid = null, BlockedTimeAnalyzer blockedTimeAnalyzer = null)
        {
            // We shouldn't advance the iterator if thread time is enabled because we need
            //   to add an extra frame to the caller stack that is not in the frameIterator.
            //   i.e. Short-circuiting prevents the frameIterator from doing MoveNext :)
            if (blockedTimeAnalyzer == null && !frameIterator.MoveNext())
            {
                return(StackSourceCallStackIndex.Invalid);
            }

            StackSourceFrameIndex frameIndex;
            string frameDisplayName;

            if (blockedTimeAnalyzer != null)
            {
                // If doThreadTime is true, then we need to make sure that threadid is not null
                Contract.Requires(threadid != null, nameof(threadid));

                if (blockedTimeAnalyzer.IsThreadBlocked((int)threadid))
                {
                    frameDisplayName = LinuxThreadState.BLOCKED_TIME.ToString();
                }
                else
                {
                    frameDisplayName = LinuxThreadState.CPU_TIME.ToString();
                }
            }
            else
            {
                frameDisplayName = frameIterator.Current.DisplayName;
            }

            frameIndex = InternFrame(frameDisplayName);

            stackIndex = InternCallerStack(frameIndex, InternFrames(frameIterator, stackIndex, processID));

            return(stackIndex);
        }
        protected override void DoInterning()
        {
            int threadCount = MaxThreadCount;

            frames = new ConcurrentDictionary <string, StackSourceFrameIndex>();

            parser.SkipPreamble(masterSource);

            Task[] tasks = new Task[threadCount];

            List <BlockedTimeAnalyzer>[] threadBlockedTimeAnalyzers = null;
            if (doThreadTime)
            {
                threadBlockedTimeAnalyzers = new List <BlockedTimeAnalyzer> [tasks.Length];
            }

            List <StackSourceSample>[] threadSamples = new List <StackSourceSample> [tasks.Length];

            for (int i = 0; i < tasks.Length; i++)
            {
                threadSamples[i] = new List <StackSourceSample>();

                if (threadBlockedTimeAnalyzers != null)
                {
                    threadBlockedTimeAnalyzers[i] = new List <BlockedTimeAnalyzer>();
                }

                var currentCulture   = Thread.CurrentThread.CurrentCulture;
                var currentUICulture = Thread.CurrentThread.CurrentUICulture;
                tasks[i] = new Task((object givenArrayIndex) =>
                {
                    var oldCultures = Tuple.Create(Thread.CurrentThread.CurrentCulture, Thread.CurrentThread.CurrentUICulture);

                    try
                    {
                        Thread.CurrentThread.CurrentCulture   = currentCulture;
                        Thread.CurrentThread.CurrentUICulture = currentUICulture;

                        FastStream bufferPart;
                        while ((bufferPart = GetNextSubStream(masterSource)) != null)
                        {
                            BlockedTimeAnalyzer blockedTimeAnalyzer = null;
                            if (threadBlockedTimeAnalyzers != null)
                            {
                                blockedTimeAnalyzer = new BlockedTimeAnalyzer();
                                threadBlockedTimeAnalyzers[(int)givenArrayIndex].Add(blockedTimeAnalyzer);
                            }

                            foreach (LinuxEvent linuxEvent in parser.Parse(bufferPart))
                            {
                                // If doThreadTime is true this is running on a single thread.
                                blockedTimeAnalyzer?.UpdateThreadState(linuxEvent);

                                StackSourceSample sample = CreateSampleFor(linuxEvent, blockedTimeAnalyzer);
                                threadSamples[(int)givenArrayIndex].Add(sample);

                                blockedTimeAnalyzer?.LinuxEventSampleAssociation(linuxEvent, sample);
                            }
                            bufferPart.Dispose();
                        }
                    }
                    finally
                    {
                        Thread.CurrentThread.CurrentCulture   = oldCultures.Item1;
                        Thread.CurrentThread.CurrentUICulture = oldCultures.Item2;
                    }
                }, i);

                tasks[i].Start();
            }

            Task.WaitAll(tasks);

            if (threadBlockedTimeAnalyzers != null)
            {
                List <BlockedTimeAnalyzer> allBlockedTimeAnalyzers = CustomExtensions.ConcatListsOfLists(threadBlockedTimeAnalyzers).ToList();
                FixBlockedTimes(allBlockedTimeAnalyzers);
                foreach (var blockedTimeAnalyzer in allBlockedTimeAnalyzers)
                {
                    TotalBlockedTime += blockedTimeAnalyzer.TotalBlockedTime;
                }
            }
            else
            {
                TotalBlockedTime = -1;
            }

            IEnumerable <StackSourceSample> allSamples = CustomExtensions.ConcatListsOfLists(threadSamples);

            AddSamples(allSamples);
        }
        /// <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);
        }